From 369c545647a4d062abd9ba9bb32b9744dc409bf5 Mon Sep 17 00:00:00 2001 From: yuyulei Date: Fri, 25 Dec 2020 14:43:25 +0800 Subject: [PATCH] wip --- client/admin_api.go | 4 +- cmd/frpc/sub/root.go | 19 +- cmd/frps/root.go | 7 +- conf/frpc_full.ini | 2 +- pkg/config/bandwidth.go | 121 ++++ pkg/config/bandwidth_test.go | 40 ++ pkg/config/client.go | 10 +- pkg/config/client_test.go | 28 +- pkg/config/proxy.go | 1014 +++++++++++++++++----------------- pkg/config/proxy_test.go | 20 +- pkg/config/server.go | 8 +- pkg/config/server_test.go | 16 +- pkg/config/types.go | 18 +- pkg/config/utils.go | 158 +----- pkg/config/value.go | 78 +++ pkg/config/visitor.go | 169 +++--- pkg/config/visitor_test.go | 14 + server/dashboard_api.go | 6 +- 18 files changed, 936 insertions(+), 796 deletions(-) create mode 100644 pkg/config/bandwidth.go create mode 100644 pkg/config/bandwidth_test.go create mode 100644 pkg/config/value.go diff --git a/client/admin_api.go b/client/admin_api.go index 297497ae..9b23b1a7 100644 --- a/client/admin_api.go +++ b/client/admin_api.go @@ -54,7 +54,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) { return } - newCommonCfg, err := config.LoadClientCommonConf(content) + newCommonCfg, err := config.UnmarshalClientConfFromIni(content) if err != nil { res.Code = 400 res.Msg = err.Error() @@ -62,7 +62,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) { return } - pxyCfgs, visitorCfgs, err := config.LoadClientBasicConf(svr.cfg.User, content, newCommonCfg.Start) + pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(svr.cfg.User, content, newCommonCfg.Start) if err != nil { res.Code = 400 res.Msg = err.Error() diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go index b7724d04..5775b601 100644 --- a/cmd/frpc/sub/root.go +++ b/cmd/frpc/sub/root.go @@ -131,7 +131,7 @@ func handleSignal(svr *client.Service) { func parseClientCommonCfg(fileType int, source interface{}) (cfg config.ClientCommonConf, err error) { if fileType == CfgFileTypeIni { - cfg, err = config.LoadClientCommonConf(source) + cfg, err = config.UnmarshalClientConfFromIni(source) } else if fileType == CfgFileTypeCmd { cfg, err = parseClientCommonCfgFromCmd() } @@ -147,7 +147,7 @@ func parseClientCommonCfg(fileType int, source interface{}) (cfg config.ClientCo } func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) { - cfg = config.DefaultClientConf() + cfg = config.GetDefaultClientConf() strs := strings.Split(serverAddr, ":") if len(strs) < 2 { @@ -183,24 +183,25 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) { return } -func runClient(cfgFilePath string) error { - content, err := config.GetRenderedConfFromFile(cfgFilePath) +func runClient(cfgFilePath string) (err error) { + var content string + content, err = config.GetRenderedConfFromFile(cfgFilePath) if err != nil { - return err + return } cfg, err := parseClientCommonCfg(CfgFileTypeIni, content) if err != nil { - return err + return } - pxyCfgs, visitorCfgs, err := config.LoadClientBasicConf(cfg.User, content, cfg.Start) + pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(cfg.User, content, cfg.Start) if err != nil { - return err + return } err = startService(cfg, pxyCfgs, visitorCfgs, cfgFilePath) - return err + return } func startService( diff --git a/cmd/frps/root.go b/cmd/frps/root.go index 4b3c5bd3..8ce211e8 100644 --- a/cmd/frps/root.go +++ b/cmd/frps/root.go @@ -104,10 +104,9 @@ var rootCmd = &cobra.Command{ var cfg config.ServerCommonConf var err error - if cfgFile != "" { log.Info("frps uses config file: %s", cfgFile) - var content []byte + var content string content, err = config.GetRenderedConfFromFile(cfgFile) if err != nil { return err @@ -138,7 +137,7 @@ func Execute() { func parseServerCommonCfg(fileType int, source interface{}) (cfg config.ServerCommonConf, err error) { if fileType == CfgFileTypeIni { - cfg, err = config.LoadServerCommonConf(source) + cfg, err = config.UnmarshalServerConfFromIni(source) } else if fileType == CfgFileTypeCmd { cfg, err = parseServerCommonCfgFromCmd() } @@ -154,7 +153,7 @@ func parseServerCommonCfg(fileType int, source interface{}) (cfg config.ServerCo } func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) { - cfg = config.DefaultServerConf() + cfg = config.GetDefaultServerConf() cfg.BindAddr = bindAddr cfg.BindPort = bindPort diff --git a/conf/frpc_full.ini b/conf/frpc_full.ini index 7eb62187..1b5c700e 100644 --- a/conf/frpc_full.ini +++ b/conf/frpc_full.ini @@ -177,7 +177,7 @@ use_compression = true http_user = admin http_pwd = admin # if domain for frps is frps.com, then you can access [web01] proxy by URL http://test.frps.com -sub_domain = web01 +subdomain = web01 custom_domains = web02.yourdomain.com # locations is only available for http type locations = /,/pic diff --git a/pkg/config/bandwidth.go b/pkg/config/bandwidth.go new file mode 100644 index 00000000..062cc746 --- /dev/null +++ b/pkg/config/bandwidth.go @@ -0,0 +1,121 @@ +// Copyright 2019 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "encoding/json" + "errors" + "strconv" + "strings" +) + +const ( + MB = 1024 * 1024 + KB = 1024 +) + +type BandwidthQuantity struct { + s string // MB or KB + + i int64 // bytes +} + +func NewBandwidthQuantity(s string) (BandwidthQuantity, error) { + q := BandwidthQuantity{} + err := q.UnmarshalString(s) + if err != nil { + return q, err + } + return q, nil +} + +func MustBandwidthQuantity(s string) BandwidthQuantity { + q := BandwidthQuantity{} + err := q.UnmarshalString(s) + if err != nil { + panic(err) + } + return q +} + +func (q *BandwidthQuantity) Equal(u *BandwidthQuantity) bool { + if q == nil && u == nil { + return true + } + if q != nil && u != nil { + return q.i == u.i + } + return false +} + +func (q *BandwidthQuantity) String() string { + return q.s +} + +func (q *BandwidthQuantity) UnmarshalString(s string) error { + s = strings.TrimSpace(s) + if s == "" { + return nil + } + + var ( + base int64 + f float64 + err error + ) + if strings.HasSuffix(s, "MB") { + base = MB + fstr := strings.TrimSuffix(s, "MB") + f, err = strconv.ParseFloat(fstr, 64) + if err != nil { + return err + } + } else if strings.HasSuffix(s, "KB") { + base = KB + fstr := strings.TrimSuffix(s, "KB") + f, err = strconv.ParseFloat(fstr, 64) + if err != nil { + return err + } + } else { + return errors.New("unit not support") + } + + q.s = s + q.i = int64(f * float64(base)) + return nil +} + +func (q *BandwidthQuantity) UnmarshalJSON(b []byte) error { + if len(b) == 4 && string(b) == "null" { + return nil + } + + var str string + err := json.Unmarshal(b, &str) + if err != nil { + return err + } + + return q.UnmarshalString(str) +} + +func (q *BandwidthQuantity) MarshalJSON() ([]byte, error) { + return []byte("\"" + q.s + "\""), nil +} + +func (q *BandwidthQuantity) Bytes() int64 { + return q.i +} diff --git a/pkg/config/bandwidth_test.go b/pkg/config/bandwidth_test.go new file mode 100644 index 00000000..ab03dfd2 --- /dev/null +++ b/pkg/config/bandwidth_test.go @@ -0,0 +1,40 @@ +// Copyright 2019 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +type Wrap struct { + B BandwidthQuantity `json:"b"` + Int int `json:"int"` +} + +func TestBandwidthQuantity(t *testing.T) { + assert := assert.New(t) + + var w Wrap + err := json.Unmarshal([]byte(`{"b":"1KB","int":5}`), &w) + assert.NoError(err) + assert.EqualValues(1*KB, w.B.Bytes()) + + buf, err := json.Marshal(&w) + assert.NoError(err) + assert.Equal(`{"b":"1KB","int":5}`, string(buf)) +} diff --git a/pkg/config/client.go b/pkg/config/client.go index 5def8483..96353ea2 100644 --- a/pkg/config/client.go +++ b/pkg/config/client.go @@ -1,4 +1,4 @@ -// Copyright 2016 fatedier, fatedier@gmail.com +// Copyright 2020 The frp Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ import ( ) // GetDefaultClientConf returns a client configuration with default values. -func DefaultClientConf() ClientCommonConf { +func GetDefaultClientConf() ClientCommonConf { return ClientCommonConf{ ClientConfig: auth.GetDefaultClientConf(), ServerAddr: "0.0.0.0", @@ -87,7 +87,7 @@ func (cfg *ClientCommonConf) Check() error { } // Supported sources including: string(file path), []byte, Reader interface. -func LoadClientCommonConf(source interface{}) (ClientCommonConf, error) { +func UnmarshalClientConfFromIni(source interface{}) (ClientCommonConf, error) { f, err := ini.LoadSources(ini.LoadOptions{ Insensitive: false, InsensitiveSections: false, @@ -105,7 +105,7 @@ func LoadClientCommonConf(source interface{}) (ClientCommonConf, error) { return ClientCommonConf{}, err } - common := DefaultClientConf() + common := GetDefaultClientConf() err = s.MapTo(&common) if err != nil { return ClientCommonConf{}, err @@ -118,7 +118,7 @@ func LoadClientCommonConf(source interface{}) (ClientCommonConf, error) { // if len(startProxy) is 0, start all // otherwise just start proxies in startProxy map -func LoadClientBasicConf( +func LoadAllConfFromIni( prefix string, source interface{}, start []string, diff --git a/pkg/config/client_test.go b/pkg/config/client_test.go index 37bfe812..6f581445 100644 --- a/pkg/config/client_test.go +++ b/pkg/config/client_test.go @@ -1,3 +1,17 @@ +// Copyright 2020 The frp Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package config import ( @@ -277,7 +291,7 @@ func Test_LoadClientCommonConf(t *testing.T) { UDPPacketSize: 1509, } - common, err := LoadClientCommonConf(testClientBytesWithFull) + common, err := UnmarshalClientConfFromIni(testClientBytesWithFull) assert.NoError(err) assert.Equal(expected, common) } @@ -446,7 +460,7 @@ func Test_LoadClientBasicConf(t *testing.T) { }, }, HTTPProxySpec: HTTPProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"web02.yourdomain.com"}, SubDomain: "web01", }, @@ -472,7 +486,7 @@ func Test_LoadClientBasicConf(t *testing.T) { ProxyProtocolVersion: "v2", }, HTTPSProxySpec: HTTPSProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"web02.yourdomain.com"}, SubDomain: "web01", }, @@ -516,7 +530,7 @@ func Test_LoadClientBasicConf(t *testing.T) { }, }, TCPMuxProxySpec: TCPMuxProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"tunnel1"}, SubDomain: "", }, @@ -609,7 +623,7 @@ func Test_LoadClientBasicConf(t *testing.T) { }, }, HTTPSProxySpec: HTTPSProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"test.yourdomain.com"}, }, }, @@ -629,7 +643,7 @@ func Test_LoadClientBasicConf(t *testing.T) { }, }, HTTPProxySpec: HTTPProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"test.yourdomain.com"}, }, }, @@ -661,7 +675,7 @@ func Test_LoadClientBasicConf(t *testing.T) { }, } - proxyActual, visitorActual, err := LoadClientBasicConf(testUser, testClientBytesWithFull, nil) + proxyActual, visitorActual, err := LoadAllConfFromIni(testUser, testClientBytesWithFull, nil) assert.NoError(err) assert.Equal(proxyExpected, proxyActual) assert.Equal(visitorExpected, visitorActual) diff --git a/pkg/config/proxy.go b/pkg/config/proxy.go index ce12628b..16fcff15 100644 --- a/pkg/config/proxy.go +++ b/pkg/config/proxy.go @@ -104,7 +104,7 @@ func NewProxyConfFromIni(prefix, name string, section *ini.Section) (ProxyConf, } // Proxy loaded from msg -func NewProxyConfFromMsg(pMsg *msg.NewProxy, svrconf ServerCommonConf) (ProxyConf, error) { +func NewProxyConfFromMsg(pMsg *msg.NewProxy, serverCfg ServerCommonConf) (ProxyConf, error) { if pMsg.ProxyType == "" { pMsg.ProxyType = consts.TCPProxy } @@ -116,7 +116,7 @@ func NewProxyConfFromMsg(pMsg *msg.NewProxy, svrconf ServerCommonConf) (ProxyCon conf.UnmarshalFromMsg(pMsg) - err := conf.CheckForSvr(svrconf) + err := conf.CheckForSvr(serverCfg) if err != nil { return nil, err } @@ -134,27 +134,27 @@ func defaultBaseProxyConf(proxyType string) BaseProxyConf { } } -func (c *BaseProxyConf) GetBaseInfo() *BaseProxyConf { - return c +func (cfg *BaseProxyConf) GetBaseInfo() *BaseProxyConf { + return cfg } -func (c *BaseProxyConf) compare(cmp *BaseProxyConf) bool { - if c.ProxyName != cmp.ProxyName || - c.ProxyType != cmp.ProxyType || - c.UseEncryption != cmp.UseEncryption || - c.UseCompression != cmp.UseCompression || - c.Group != cmp.Group || - c.GroupKey != cmp.GroupKey || - c.ProxyProtocolVersion != cmp.ProxyProtocolVersion || - !c.BandwidthLimit.Equal(&cmp.BandwidthLimit) || - !reflect.DeepEqual(c.Metas, cmp.Metas) { +func (cfg *BaseProxyConf) compare(cmp *BaseProxyConf) bool { + if cfg.ProxyName != cmp.ProxyName || + cfg.ProxyType != cmp.ProxyType || + cfg.UseEncryption != cmp.UseEncryption || + cfg.UseCompression != cmp.UseCompression || + cfg.Group != cmp.Group || + cfg.GroupKey != cmp.GroupKey || + cfg.ProxyProtocolVersion != cmp.ProxyProtocolVersion || + !cfg.BandwidthLimit.Equal(&cmp.BandwidthLimit) || + !reflect.DeepEqual(cfg.Metas, cmp.Metas) { return false } - if !reflect.DeepEqual(c.LocalSvrConf, cmp.LocalSvrConf) { + if !reflect.DeepEqual(cfg.LocalSvrConf, cmp.LocalSvrConf) { return false } - if !reflect.DeepEqual(c.HealthCheckConf, cmp.HealthCheckConf) { + if !reflect.DeepEqual(cfg.HealthCheckConf, cmp.HealthCheckConf) { return false } @@ -162,88 +162,128 @@ func (c *BaseProxyConf) compare(cmp *BaseProxyConf) bool { } // BaseProxyConf apply custom logic changes. -func (c *BaseProxyConf) decorate(prefix string, name string, section *ini.Section) error { +func (cfg *BaseProxyConf) decorate(prefix string, name string, section *ini.Section) error { // proxy_name - c.ProxyName = prefix + name + cfg.ProxyName = prefix + name // metas_xxx - c.Metas = GetMapWithoutPrefix(section.KeysHash(), "meta_") + cfg.Metas = GetMapWithoutPrefix(section.KeysHash(), "meta_") // bandwidth_limit if bandwidth, err := section.GetKey("bandwidth_limit"); err == nil { - c.BandwidthLimit, err = NewBandwidthQuantity(bandwidth.String()) + cfg.BandwidthLimit, err = NewBandwidthQuantity(bandwidth.String()) if err != nil { return err } } // plugin_xxx - c.LocalSvrConf.PluginParams = GetMapByPrefix(section.KeysHash(), "plugin_") + cfg.LocalSvrConf.PluginParams = GetMapByPrefix(section.KeysHash(), "plugin_") // custom logic code - if c.HealthCheckType == "tcp" && c.Plugin == "" { - c.HealthCheckAddr = c.LocalIP + fmt.Sprintf(":%d", c.LocalPort) + if cfg.HealthCheckType == "tcp" && cfg.Plugin == "" { + cfg.HealthCheckAddr = cfg.LocalIP + fmt.Sprintf(":%d", cfg.LocalPort) } - if c.HealthCheckType == "http" && c.Plugin == "" && c.HealthCheckURL != "" { - s := fmt.Sprintf("http://%s:%d", c.LocalIP, c.LocalPort) - if !strings.HasPrefix(c.HealthCheckURL, "/") { + if cfg.HealthCheckType == "http" && cfg.Plugin == "" && cfg.HealthCheckURL != "" { + s := fmt.Sprintf("http://%s:%d", cfg.LocalIP, cfg.LocalPort) + if !strings.HasPrefix(cfg.HealthCheckURL, "/") { s += "/" } - c.HealthCheckURL = s + c.HealthCheckURL + cfg.HealthCheckURL = s + cfg.HealthCheckURL } return nil } -func (c *BaseProxyConf) unmarshalFromMsg(pMsg *msg.NewProxy) { - c.ProxyName = pMsg.ProxyName - c.ProxyType = pMsg.ProxyType - c.UseEncryption = pMsg.UseEncryption - c.UseCompression = pMsg.UseCompression - c.Group = pMsg.Group - c.GroupKey = pMsg.GroupKey - c.Metas = pMsg.Metas +func (cfg *BaseProxyConf) marshalToMsg(pMsg *msg.NewProxy) { + pMsg.ProxyName = cfg.ProxyName + pMsg.ProxyType = cfg.ProxyType + pMsg.UseEncryption = cfg.UseEncryption + pMsg.UseCompression = cfg.UseCompression + pMsg.Group = cfg.Group + pMsg.GroupKey = cfg.GroupKey + pMsg.Metas = cfg.Metas } -func (c *BaseProxyConf) marshalToMsg(pMsg *msg.NewProxy) { - pMsg.ProxyName = c.ProxyName - pMsg.ProxyType = c.ProxyType - pMsg.UseEncryption = c.UseEncryption - pMsg.UseCompression = c.UseCompression - pMsg.Group = c.Group - pMsg.GroupKey = c.GroupKey - pMsg.Metas = c.Metas +func (cfg *BaseProxyConf) unmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.ProxyName = pMsg.ProxyName + cfg.ProxyType = pMsg.ProxyType + cfg.UseEncryption = pMsg.UseEncryption + cfg.UseCompression = pMsg.UseCompression + cfg.Group = pMsg.Group + cfg.GroupKey = pMsg.GroupKey + cfg.Metas = pMsg.Metas } -func (c *BaseProxyConf) checkForCli() error { - if c.ProxyProtocolVersion != "" { - if c.ProxyProtocolVersion != "v1" && c.ProxyProtocolVersion != "v2" { - return fmt.Errorf("no support proxy protocol version: %s", c.ProxyProtocolVersion) +func (cfg *BaseProxyConf) checkForCli() (err error) { + if cfg.ProxyProtocolVersion != "" { + if cfg.ProxyProtocolVersion != "v1" && cfg.ProxyProtocolVersion != "v2" { + return fmt.Errorf("no support proxy protocol version: %s", cfg.ProxyProtocolVersion) } } - if err := c.LocalSvrConf.validate(); err != nil { - return err + if err = cfg.LocalSvrConf.checkForCli(); err != nil { + return } - if err := c.HealthCheckConf.validate(); err != nil { - return err + if err = cfg.HealthCheckConf.checkForCli(); err != nil { + return } return nil } -func (c *BaseProxyConf) checkForSvr(conf ServerCommonConf) error { +func (cfg *BaseProxyConf) checkForSvr(conf ServerCommonConf) error { + return nil +} + +// DomainConf +func (cfg *DomainConf) check() (err error) { + if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" { + err = fmt.Errorf("custom_domains and subdomain should set at least one of them") + return + } + return +} + +func (cfg *DomainConf) checkForCli() (err error) { + if err = cfg.check(); err != nil { + return + } + return +} + +func (cfg *DomainConf) checkForSvr(serverCfg ServerCommonConf) (err error) { + if err = cfg.check(); err != nil { + return + } + + for _, domain := range cfg.CustomDomains { + if serverCfg.SubDomainHost != "" && len(strings.Split(serverCfg.SubDomainHost, ".")) < len(strings.Split(domain, ".")) { + if strings.Contains(domain, serverCfg.SubDomainHost) { + return fmt.Errorf("custom domain [%s] should not belong to subdomain_host [%s]", domain, serverCfg.SubDomainHost) + } + } + } + + if cfg.SubDomain != "" { + if serverCfg.SubDomainHost == "" { + return fmt.Errorf("subdomain is not supported because this feature is not enabled in remote frps") + } + if strings.Contains(cfg.SubDomain, ".") || strings.Contains(cfg.SubDomain, "*") { + return fmt.Errorf("'.' and '*' is not supported in subdomain") + } + } return nil } // LocalSvrConf -func (c *LocalSvrConf) validate() (err error) { - if c.Plugin == "" { - if c.LocalIP == "" { +func (cfg *LocalSvrConf) checkForCli() (err error) { + if cfg.Plugin == "" { + if cfg.LocalIP == "" { err = fmt.Errorf("local ip or plugin is required") return } - if c.LocalPort <= 0 { + if cfg.LocalPort <= 0 { err = fmt.Errorf("error local_port") return } @@ -252,252 +292,53 @@ func (c *LocalSvrConf) validate() (err error) { } // HealthCheckConf -func (c *HealthCheckConf) validate() error { - if c.HealthCheckType != "" && c.HealthCheckType != "tcp" && c.HealthCheckType != "http" { +func (cfg *HealthCheckConf) checkForCli() error { + if cfg.HealthCheckType != "" && cfg.HealthCheckType != "tcp" && cfg.HealthCheckType != "http" { return fmt.Errorf("unsupport health check type") } - if c.HealthCheckType != "" { - if c.HealthCheckType == "http" && c.HealthCheckURL == "" { + if cfg.HealthCheckType != "" { + if cfg.HealthCheckType == "http" && cfg.HealthCheckURL == "" { return fmt.Errorf("health_check_url is required for health check type 'http'") } } return nil } -// DomainSpec -func (c *DomainSpec) validate() error { - if len(c.CustomDomains) == 0 && c.SubDomain == "" { - return fmt.Errorf("custom_domains and subdomain should set at least one of them") - } - return nil -} - -func (c *DomainSpec) validateForCli() error { - if err := c.validate(); err != nil { - return err - } - return nil -} - -func (c *DomainSpec) validateForSvr(svrconf ServerCommonConf) error { - if err := c.validate(); err != nil { - return err - } - - for _, domain := range c.CustomDomains { - if svrconf.SubDomainHost != "" && len(strings.Split(svrconf.SubDomainHost, ".")) < len(strings.Split(domain, ".")) { - if strings.Contains(domain, svrconf.SubDomainHost) { - return fmt.Errorf("custom domain [%s] should not belong to subdomain_host [%s]", domain, svrconf.SubDomainHost) - } - } - } - - if c.SubDomain != "" { - if svrconf.SubDomainHost == "" { - return fmt.Errorf("subdomain is not supported because this feature is not enabled in remote frps") - } - if strings.Contains(c.SubDomain, ".") || strings.Contains(c.SubDomain, "*") { - return fmt.Errorf("'.' and '*' is not supported in subdomain") - } - } - return nil -} - -// HTTP -var _ ProxyConf = &HTTPProxyConf{} - -func (c *HTTPProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*HTTPProxyConf) - if !ok { - return false - } - - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { - return false - } - - // Add custom logic equal if exists. - if !reflect.DeepEqual(c.HTTPProxySpec, cmp.HTTPProxySpec) { - return false - } - - return true -} - -func (c *HTTPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) - if err != nil { - return err - } - - err = c.BaseProxyConf.decorate(prefix, name, section) - if err != nil { - return err - } - - // Add custom logic unmarshal if exists - c.Headers = GetMapWithoutPrefix(section.KeysHash(), "header_") - - return nil -} - -func (c *HTTPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) - - // Add custom logic unmarshal if exists - c.CustomDomains = pMsg.CustomDomains - c.SubDomain = pMsg.SubDomain - c.Locations = pMsg.Locations - c.HostHeaderRewrite = pMsg.HostHeaderRewrite - c.HTTPUser = pMsg.HTTPUser - c.HTTPPwd = pMsg.HTTPPwd - c.Headers = pMsg.Headers -} - -func (c *HTTPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) - - // Add custom logic marshal if exists - pMsg.CustomDomains = c.CustomDomains - pMsg.SubDomain = c.SubDomain - pMsg.Locations = c.Locations - pMsg.HostHeaderRewrite = c.HostHeaderRewrite - pMsg.HTTPUser = c.HTTPUser - pMsg.HTTPPwd = c.HTTPPwd - pMsg.Headers = c.Headers -} - -func (c *HTTPProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err - } - - // Add custom logic check if exists - if err := c.DomainSpec.validateForCli(); err != nil { - return err - } - - return nil -} - -func (c *HTTPProxyConf) CheckForSvr(svrconf ServerCommonConf) error { - if svrconf.VhostHTTPPort == 0 { - return fmt.Errorf("type [http] not support when vhost_http_port is not set") - } - - if err := c.DomainSpec.validateForSvr(svrconf); err != nil { - return fmt.Errorf("proxy [%s] domain conf check error: %v", c.ProxyName, err) - } - - return nil -} - -// HTTPS -var _ ProxyConf = &HTTPSProxyConf{} - -func (c *HTTPSProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*HTTPSProxyConf) - if !ok { - return false - } - - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { - return false - } - - // Add custom logic equal if exists. - if !reflect.DeepEqual(c.HTTPSProxySpec, cmp.HTTPSProxySpec) { - return false - } - - return true -} - -func (c *HTTPSProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) - if err != nil { - return err - } - - err = c.BaseProxyConf.decorate(prefix, name, section) - if err != nil { - return err - } - - // Add custom logic unmarshal if exists - - return nil -} - -func (c *HTTPSProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) - - // Add custom logic unmarshal if exists - c.CustomDomains = pMsg.CustomDomains - c.SubDomain = pMsg.SubDomain -} - -func (c *HTTPSProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) - - // Add custom logic marshal if exists - pMsg.CustomDomains = c.CustomDomains - pMsg.SubDomain = c.SubDomain -} - -func (c *HTTPSProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err - } - - // Add custom logic check if exists - if err := c.DomainSpec.validateForCli(); err != nil { - return err - } - - return nil -} - -func (c *HTTPSProxyConf) CheckForSvr(svrconf ServerCommonConf) error { - if svrconf.VhostHTTPSPort == 0 { - return fmt.Errorf("type [https] not support when vhost_https_port is not set") - } - - if err := c.DomainSpec.validateForSvr(svrconf); err != nil { - return fmt.Errorf("proxy [%s] domain conf check error: %v", c.ProxyName, err) - } - - return nil -} - // TCP var _ ProxyConf = &TCPProxyConf{} -func (c *TCPProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*TCPProxyConf) +func (cfg *TCPProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*TCPProxyConf) if !ok { return false } - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { return false } // Add custom logic equal if exists. - if !reflect.DeepEqual(c.TCPProxySpec, cmp.TCPProxySpec) { + if !reflect.DeepEqual(cfg.TCPProxySpec, cmpConf.TCPProxySpec) { return false } return true } -func (c *TCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) +func (cfg *TCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) + + // Add custom logic unmarshal if exists + cfg.RemotePort = pMsg.RemotePort +} + +func (cfg *TCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) if err != nil { return err } - err = c.BaseProxyConf.decorate(prefix, name, section) + err = cfg.BaseProxyConf.decorate(prefix, name, section) if err != nil { return err } @@ -507,62 +348,55 @@ func (c *TCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini return nil } -func (c *TCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) - - // Add custom logic unmarshal if exists - c.RemotePort = pMsg.RemotePort -} - -func (c *TCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) +func (cfg *TCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) // Add custom logic marshal if exists - pMsg.RemotePort = c.RemotePort + pMsg.RemotePort = cfg.RemotePort } -func (c *TCPProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err +func (cfg *TCPProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return } // Add custom logic check if exists - return nil + return } -func (c *TCPProxyConf) CheckForSvr(svrconf ServerCommonConf) error { +func (cfg *TCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { return nil } // TCPMux var _ ProxyConf = &TCPMuxProxyConf{} -func (c *TCPMuxProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*TCPMuxProxyConf) +func (cfg *TCPMuxProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*TCPMuxProxyConf) if !ok { return false } - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { return false } // Add custom logic equal if exists. - if !reflect.DeepEqual(c.TCPMuxProxySpec, cmp.TCPMuxProxySpec) { + if !reflect.DeepEqual(cfg.TCPMuxProxySpec, cmpConf.TCPMuxProxySpec) { return false } return true } -func (c *TCPMuxProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) +func (cfg *TCPMuxProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) if err != nil { return err } - err = c.BaseProxyConf.decorate(prefix, name, section) + err = cfg.BaseProxyConf.decorate(prefix, name, section) if err != nil { return err } @@ -572,333 +406,501 @@ func (c *TCPMuxProxyConf) UnmarshalFromIni(prefix string, name string, section * return nil } -func (c *TCPMuxProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) +func (cfg *TCPMuxProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) // Add custom logic unmarshal if exists - c.CustomDomains = pMsg.CustomDomains - c.SubDomain = pMsg.SubDomain - c.Multiplexer = pMsg.Multiplexer + cfg.CustomDomains = pMsg.CustomDomains + cfg.SubDomain = pMsg.SubDomain + cfg.Multiplexer = pMsg.Multiplexer } -func (c *TCPMuxProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) +func (cfg *TCPMuxProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) // Add custom logic marshal if exists - pMsg.CustomDomains = c.CustomDomains - pMsg.SubDomain = c.SubDomain - pMsg.Multiplexer = c.Multiplexer + pMsg.CustomDomains = cfg.CustomDomains + pMsg.SubDomain = cfg.SubDomain + pMsg.Multiplexer = cfg.Multiplexer } -func (c *TCPMuxProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { +func (cfg *TCPMuxProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return + } + + // Add custom logic check if exists + if err = cfg.DomainConf.checkForCli(); err != nil { + return + } + + if cfg.Multiplexer != consts.HTTPConnectTCPMultiplexer { + return fmt.Errorf("parse conf error: incorrect multiplexer [%s]", cfg.Multiplexer) + } + + return +} + +func (cfg *TCPMuxProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) { + if cfg.Multiplexer != consts.HTTPConnectTCPMultiplexer { + return fmt.Errorf("proxy [%s] incorrect multiplexer [%s]", cfg.ProxyName, cfg.Multiplexer) + } + + if cfg.Multiplexer == consts.HTTPConnectTCPMultiplexer && serverCfg.TCPMuxHTTPConnectPort == 0 { + return fmt.Errorf("proxy [%s] type [tcpmux] with multiplexer [httpconnect] requires tcpmux_httpconnect_port configuration", cfg.ProxyName) + } + + if err = cfg.DomainConf.checkForSvr(serverCfg); err != nil { + err = fmt.Errorf("proxy [%s] domain conf check error: %v", cfg.ProxyName, err) + return + } + + return +} + +// UDP +var _ ProxyConf = &UDPProxyConf{} + +func (cfg *UDPProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*UDPProxyConf) + if !ok { + return false + } + + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { + return false + } + + // Add custom logic equal if exists. + if !reflect.DeepEqual(cfg.UDPProxySpec, cmpConf.UDPProxySpec) { + return false + } + + return true +} + +func (cfg *UDPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) + if err != nil { + return err + } + + err = cfg.BaseProxyConf.decorate(prefix, name, section) + if err != nil { + return err + } + + // Add custom logic unmarshal if exists + + return nil +} + +func (cfg *UDPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) + + // Add custom logic unmarshal if exists + cfg.RemotePort = pMsg.RemotePort +} + +func (cfg *UDPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) + + // Add custom logic marshal if exists + pMsg.RemotePort = cfg.RemotePort +} + +func (cfg *UDPProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return + } + + // Add custom logic check if exists + + return +} + +func (cfg *UDPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { + return nil +} + +// HTTP +var _ ProxyConf = &HTTPProxyConf{} + +func (cfg *HTTPProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*HTTPProxyConf) + if !ok { + return false + } + + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { + return false + } + + // Add custom logic equal if exists. + if !reflect.DeepEqual(cfg.HTTPProxySpec, cmpConf.HTTPProxySpec) { + return false + } + + return true +} + +func (cfg *HTTPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) + if err != nil { + return err + } + + err = cfg.BaseProxyConf.decorate(prefix, name, section) + if err != nil { + return err + } + + // Add custom logic unmarshal if exists + cfg.Headers = GetMapWithoutPrefix(section.KeysHash(), "header_") + + return nil +} + +func (cfg *HTTPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) + + // Add custom logic unmarshal if exists + cfg.CustomDomains = pMsg.CustomDomains + cfg.SubDomain = pMsg.SubDomain + cfg.Locations = pMsg.Locations + cfg.HostHeaderRewrite = pMsg.HostHeaderRewrite + cfg.HTTPUser = pMsg.HTTPUser + cfg.HTTPPwd = pMsg.HTTPPwd + cfg.Headers = pMsg.Headers +} + +func (cfg *HTTPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) + + // Add custom logic marshal if exists + pMsg.CustomDomains = cfg.CustomDomains + pMsg.SubDomain = cfg.SubDomain + pMsg.Locations = cfg.Locations + pMsg.HostHeaderRewrite = cfg.HostHeaderRewrite + pMsg.HTTPUser = cfg.HTTPUser + pMsg.HTTPPwd = cfg.HTTPPwd + pMsg.Headers = cfg.Headers +} + +func (cfg *HTTPProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return + } + + // Add custom logic check if exists + if err = cfg.DomainConf.checkForCli(); err != nil { + return + } + + return +} + +func (cfg *HTTPProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) { + if serverCfg.VhostHTTPPort == 0 { + return fmt.Errorf("type [http] not support when vhost_http_port is not set") + } + + if err = cfg.DomainConf.checkForSvr(serverCfg); err != nil { + err = fmt.Errorf("proxy [%s] domain conf check error: %v", cfg.ProxyName, err) + return + } + + return +} + +// HTTPS +var _ ProxyConf = &HTTPSProxyConf{} + +func (cfg *HTTPSProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*HTTPSProxyConf) + if !ok { + return false + } + + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { + return false + } + + // Add custom logic equal if exists. + if !reflect.DeepEqual(cfg.HTTPSProxySpec, cmpConf.HTTPSProxySpec) { + return false + } + + return true +} + +func (cfg *HTTPSProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) + if err != nil { + return err + } + + err = cfg.BaseProxyConf.decorate(prefix, name, section) + if err != nil { + return err + } + + // Add custom logic unmarshal if exists + + return nil +} + +func (cfg *HTTPSProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) + + // Add custom logic unmarshal if exists + cfg.CustomDomains = pMsg.CustomDomains + cfg.SubDomain = pMsg.SubDomain +} + +func (cfg *HTTPSProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) + + // Add custom logic marshal if exists + pMsg.CustomDomains = cfg.CustomDomains + pMsg.SubDomain = cfg.SubDomain +} + +func (cfg *HTTPSProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return + } + + // Add custom logic check if exists + if err = cfg.DomainConf.checkForCli(); err != nil { + return + } + + return +} + +func (cfg *HTTPSProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) { + if serverCfg.VhostHTTPSPort == 0 { + return fmt.Errorf("type [https] not support when vhost_https_port is not set") + } + + if err = cfg.DomainConf.checkForSvr(serverCfg); err != nil { + err = fmt.Errorf("proxy [%s] domain conf check error: %v", cfg.ProxyName, err) + return + } + + return +} + +// SUDP +var _ ProxyConf = &SUDPProxyConf{} + +func (cfg *SUDPProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*SUDPProxyConf) + if !ok { + return false + } + + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { + return false + } + + // Add custom logic equal if exists. + if !reflect.DeepEqual(cfg.SUDPProxySpec, cmpConf.SUDPProxySpec) { + return false + } + + return true +} + +func (cfg *SUDPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) + if err != nil { + return err + } + + err = cfg.BaseProxyConf.decorate(prefix, name, section) + if err != nil { + return err + } + + // Add custom logic unmarshal if exists + + return nil +} + +// Only for role server. +func (cfg *SUDPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) + + // Add custom logic unmarshal if exists + cfg.Sk = pMsg.Sk +} + +func (cfg *SUDPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) + + // Add custom logic marshal if exists + pMsg.Sk = cfg.Sk +} + +func (cfg *SUDPProxyConf) CheckForCli() (err error) { + if err := cfg.BaseProxyConf.checkForCli(); err != nil { return err } // Add custom logic check if exists - if err := c.DomainSpec.validateForCli(); err != nil { - return err - } - - if c.Multiplexer != consts.HTTPConnectTCPMultiplexer { - return fmt.Errorf("parse conf error: incorrect multiplexer [%s]", c.Multiplexer) + if cfg.Role != "server" { + return fmt.Errorf("role should be 'server'") } return nil } -func (c *TCPMuxProxyConf) CheckForSvr(svrconf ServerCommonConf) error { - if c.Multiplexer != consts.HTTPConnectTCPMultiplexer { - return fmt.Errorf("proxy [%s] incorrect multiplexer [%s]", c.ProxyName, c.Multiplexer) - } - - if c.Multiplexer == consts.HTTPConnectTCPMultiplexer && svrconf.TCPMuxHTTPConnectPort == 0 { - return fmt.Errorf("proxy [%s] type [tcpmux] with multiplexer [httpconnect] requires tcpmux_httpconnect_port configuration", c.ProxyName) - } - - if err := c.DomainSpec.validateForSvr(svrconf); err != nil { - return fmt.Errorf("proxy [%s] domain conf check error: %v", c.ProxyName, err) - } - +func (cfg *SUDPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { return nil } // STCP var _ ProxyConf = &STCPProxyConf{} -func (c *STCPProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*STCPProxyConf) +func (cfg *STCPProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*STCPProxyConf) if !ok { return false } - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { return false } // Add custom logic equal if exists. - if !reflect.DeepEqual(c.STCPProxySpec, cmp.STCPProxySpec) { + if !reflect.DeepEqual(cfg.STCPProxySpec, cmpConf.STCPProxySpec) { return false } return true } -func (c *STCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) +func (cfg *STCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) if err != nil { return err } - err = c.BaseProxyConf.decorate(prefix, name, section) + err = cfg.BaseProxyConf.decorate(prefix, name, section) if err != nil { return err } // Add custom logic unmarshal if exists - if c.Role == "" { - c.Role = "server" + if cfg.Role == "" { + cfg.Role = "server" } return nil } // Only for role server. -func (c *STCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) +func (cfg *STCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) // Add custom logic unmarshal if exists - c.Sk = pMsg.Sk + cfg.Sk = pMsg.Sk } -func (c *STCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) +func (cfg *STCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) // Add custom logic marshal if exists - pMsg.Sk = c.Sk + pMsg.Sk = cfg.Sk } -func (c *STCPProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err +func (cfg *STCPProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return } // Add custom logic check if exists - if c.Role != "server" { + if cfg.Role != "server" { return fmt.Errorf("role should be 'server'") } - return nil + return } -func (c *STCPProxyConf) CheckForSvr(svrconf ServerCommonConf) error { +func (cfg *STCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { return nil } // XTCP var _ ProxyConf = &XTCPProxyConf{} -func (c *XTCPProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*XTCPProxyConf) +func (cfg *XTCPProxyConf) Compare(cmp ProxyConf) bool { + cmpConf, ok := cmp.(*XTCPProxyConf) if !ok { return false } - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { + if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) { return false } // Add custom logic equal if exists. - if !reflect.DeepEqual(c.XTCPProxySpec, cmp.XTCPProxySpec) { + if !reflect.DeepEqual(cfg.XTCPProxySpec, cmpConf.XTCPProxySpec) { return false } return true } -func (c *XTCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) +func (cfg *XTCPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) if err != nil { return err } - err = c.BaseProxyConf.decorate(prefix, name, section) + err = cfg.BaseProxyConf.decorate(prefix, name, section) if err != nil { return err } // Add custom logic unmarshal if exists - if c.Role == "" { - c.Role = "server" + if cfg.Role == "" { + cfg.Role = "server" } return nil } // Only for role server. -func (c *XTCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) +func (cfg *XTCPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.unmarshalFromMsg(pMsg) // Add custom logic unmarshal if exists - c.Sk = pMsg.Sk + cfg.Sk = pMsg.Sk } -func (c *XTCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) +func (cfg *XTCPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.marshalToMsg(pMsg) // Add custom logic marshal if exists - pMsg.Sk = c.Sk + pMsg.Sk = cfg.Sk } -func (c *XTCPProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err +func (cfg *XTCPProxyConf) CheckForCli() (err error) { + if err = cfg.BaseProxyConf.checkForCli(); err != nil { + return } // Add custom logic check if exists - if c.Role != "server" { + if cfg.Role != "server" { return fmt.Errorf("role should be 'server'") } - return nil -} - -func (c *XTCPProxyConf) CheckForSvr(svrconf ServerCommonConf) error { - return nil -} - -// UDP - -var _ ProxyConf = &UDPProxyConf{} - -func (c *UDPProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*UDPProxyConf) - if !ok { - return false - } - - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { - return false - } - - // Add custom logic equal if exists. - if !reflect.DeepEqual(c.UDPProxySpec, cmp.UDPProxySpec) { - return false - } - - return true -} - -func (c *UDPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) - if err != nil { - return err - } - - err = c.BaseProxyConf.decorate(prefix, name, section) - if err != nil { - return err - } - - // Add custom logic unmarshal if exists - - return nil -} - -func (c *UDPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) - - // Add custom logic unmarshal if exists - c.RemotePort = pMsg.RemotePort -} - -func (c *UDPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) - - // Add custom logic marshal if exists - pMsg.RemotePort = c.RemotePort -} - -func (c *UDPProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err - } - - // Add custom logic check if exists - - return nil -} - -func (c *UDPProxyConf) CheckForSvr(svrconf ServerCommonConf) error { - return nil -} - -// SUDP - -var _ ProxyConf = &SUDPProxyConf{} - -func (c *SUDPProxyConf) Compare(conf ProxyConf) bool { - cmp, ok := conf.(*SUDPProxyConf) - if !ok { - return false - } - - if !c.BaseProxyConf.compare(&cmp.BaseProxyConf) { - return false - } - - // Add custom logic equal if exists. - if !reflect.DeepEqual(c.SUDPProxySpec, cmp.SUDPProxySpec) { - return false - } - - return true -} - -func (c *SUDPProxyConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) - if err != nil { - return err - } - - err = c.BaseProxyConf.decorate(prefix, name, section) - if err != nil { - return err - } - - // Add custom logic unmarshal if exists - - return nil -} - -// Only for role server. -func (c *SUDPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.unmarshalFromMsg(pMsg) - - // Add custom logic unmarshal if exists - c.Sk = pMsg.Sk -} - -func (c *SUDPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { - c.BaseProxyConf.marshalToMsg(pMsg) - - // Add custom logic marshal if exists - pMsg.Sk = c.Sk -} - -func (c *SUDPProxyConf) CheckForCli() error { - if err := c.BaseProxyConf.checkForCli(); err != nil { - return err - } - - // Add custom logic check if exists - if c.Role != "server" { - return fmt.Errorf("role should be 'server'") - } - - return nil -} - -func (c *SUDPProxyConf) CheckForSvr(svrconf ServerCommonConf) error { + return +} + +func (cfg *XTCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { return nil } diff --git a/pkg/config/proxy_test.go b/pkg/config/proxy_test.go index b9104892..fef6a0cc 100644 --- a/pkg/config/proxy_test.go +++ b/pkg/config/proxy_test.go @@ -1,3 +1,17 @@ +// Copyright 2020 The frp Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package config import ( @@ -171,7 +185,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { }, }, HTTPProxySpec: HTTPProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"web02.yourdomain.com"}, SubDomain: "web01", }, @@ -211,7 +225,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { ProxyProtocolVersion: "v2", }, HTTPSProxySpec: HTTPSProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"web02.yourdomain.com"}, SubDomain: "web01", }, @@ -290,7 +304,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { }, }, TCPMuxProxySpec: TCPMuxProxySpec{ - DomainSpec: DomainSpec{ + DomainConf: DomainConf{ CustomDomains: []string{"tunnel1"}, SubDomain: "", }, diff --git a/pkg/config/server.go b/pkg/config/server.go index 8a33c1c3..888acba3 100644 --- a/pkg/config/server.go +++ b/pkg/config/server.go @@ -1,4 +1,4 @@ -// Copyright 2016 fatedier, fatedier@gmail.com +// Copyright 2020 The frp Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import ( // GetDefaultServerConf returns a server configuration with reasonable // defaults. -func DefaultServerConf() ServerCommonConf { +func GetDefaultServerConf() ServerCommonConf { return ServerCommonConf{ ServerConfig: auth.GetDefaultServerConf(), BindAddr: "0.0.0.0", @@ -72,7 +72,7 @@ func (cfg *ServerCommonConf) Check() error { return nil } -func LoadServerCommonConf(source interface{}) (ServerCommonConf, error) { +func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) { f, err := ini.LoadSources(ini.LoadOptions{ Insensitive: false, @@ -91,7 +91,7 @@ func LoadServerCommonConf(source interface{}) (ServerCommonConf, error) { return ServerCommonConf{}, err } - common := DefaultServerConf() + common := GetDefaultServerConf() err = s.MapTo(&common) if err != nil { return ServerCommonConf{}, err diff --git a/pkg/config/server_test.go b/pkg/config/server_test.go index 4a7b4526..19a962d8 100644 --- a/pkg/config/server_test.go +++ b/pkg/config/server_test.go @@ -1,3 +1,17 @@ +// Copyright 2020 The frp Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package config import ( @@ -184,7 +198,7 @@ func Test_LoadServerCommonConf(t *testing.T) { } for _, c := range testcases { - actual, err := LoadServerCommonConf(c.source) + actual, err := UnmarshalServerConfFromIni(c.source) assert.NoError(err) assert.Equal(c.expected, actual) } diff --git a/pkg/config/types.go b/pkg/config/types.go index cee362ad..1def458f 100644 --- a/pkg/config/types.go +++ b/pkg/config/types.go @@ -1,4 +1,4 @@ -// Copyright 2019 fatedier, fatedier@gmail.com +// Copyright 2020 The frp Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,7 +25,9 @@ import ( "gopkg.in/ini.v1" ) -// Client +// ClientCommonConf contains information for a client service. It is +// recommended to use GetDefaultClientConf instead of creating this object +// directly, so that all unspecified fields have reasonable default values. type ClientCommonConf struct { auth.ClientConfig `ini:",,,,extends",json:"inline"` // ServerAddr specifies the address of the server to connect to. By @@ -96,7 +98,7 @@ type ClientCommonConf struct { // Start specifies a set of enabled proxies by name. If this set is empty, // all supplied proxies are enabled. By default, this value is an empty // set. - Start []string `ini:"start",json:"start""` + Start []string `ini:"start",json:"start"` //Start map[string]struct{} `json:"start"` // Protocol specifies the protocol to use when interacting with the server. // Valid values are "tcp", "kcp" and "websocket". By default, this value @@ -132,8 +134,6 @@ type ClientCommonConf struct { UDPPacketSize int64 `ini:"udp_packet_size",json:"udp_packet_size"` } -// Server - // ServerCommonConf contains information for a server service. It is // recommended to use GetDefaultServerConf instead of creating this object // directly, so that all unspecified fields have reasonable default values. @@ -387,7 +387,7 @@ type BaseProxyConf struct { HealthCheckConf `ini:",,,,extends",json:"inline"` } -type DomainSpec struct { +type DomainConf struct { CustomDomains []string `ini:"custom_domains",json:"custom_domains"` SubDomain string `ini:"subdomain",json:"subdomain"` } @@ -399,7 +399,7 @@ type HTTPProxyConf struct { } type HTTPProxySpec struct { - DomainSpec `ini:",,,,extends",json:"inline"` + DomainConf `ini:",,,,extends",json:"inline"` Locations []string `ini:"locations",json:"locations"` HTTPUser string `ini:"http_user",json:"http_user"` HTTPPwd string `ini:"http_pwd",json:"http_pwd"` @@ -414,7 +414,7 @@ type HTTPSProxyConf struct { } type HTTPSProxySpec struct { - DomainSpec `ini:",,,,extends",json:"inline"` + DomainConf `ini:",,,,extends",json:"inline"` } // TCP @@ -434,7 +434,7 @@ type TCPMuxProxyConf struct { } type TCPMuxProxySpec struct { - DomainSpec `ini:",,,,extends",json:"inline"` + DomainConf `ini:",,,,extends",json:"inline"` Multiplexer string `ini:"multiplexer"` } diff --git a/pkg/config/utils.go b/pkg/config/utils.go index 543af281..aef674d4 100644 --- a/pkg/config/utils.go +++ b/pkg/config/utils.go @@ -1,4 +1,4 @@ -// Copyright 2016 fatedier, fatedier@gmail.com +// Copyright 2020 The frp Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,14 +15,7 @@ package config import ( - "bytes" - "encoding/json" - "errors" - "io/ioutil" - "os" - "strconv" "strings" - "text/template" ) func GetMapWithoutPrefix(set map[string]string, prefix string) map[string]string { @@ -56,152 +49,3 @@ func GetMapByPrefix(set map[string]string, prefix string) map[string]string { return m } - -// Render Env Values -var glbEnvs map[string]string - -func init() { - glbEnvs = make(map[string]string) - envs := os.Environ() - for _, env := range envs { - kv := strings.Split(env, "=") - if len(kv) != 2 { - continue - } - glbEnvs[kv[0]] = kv[1] - } -} - -type Values struct { - Envs map[string]string // environment vars -} - -func GetValues() *Values { - return &Values{ - Envs: glbEnvs, - } -} - -func RenderContent(in []byte) ([]byte, error) { - tmpl, err := template.New("frp").Parse(string(in)) - if err != nil { - return nil, err - } - - buffer := bytes.NewBufferString("") - v := GetValues() - err = tmpl.Execute(buffer, v) - if err != nil { - return nil, err - } - - return buffer.Bytes(), nil -} - -func GetRenderedConfFromFile(path string) ([]byte, error) { - data, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - return RenderContent(data) -} - -// BandwidthQuantity -const ( - MB = 1024 * 1024 - KB = 1024 -) - -type BandwidthQuantity struct { - s string // MB or KB - - i int64 // bytes -} - -func NewBandwidthQuantity(s string) (BandwidthQuantity, error) { - q := BandwidthQuantity{} - err := q.UnmarshalString(s) - if err != nil { - return q, err - } - return q, nil -} - -func MustBandwidthQuantity(s string) BandwidthQuantity { - q := BandwidthQuantity{} - err := q.UnmarshalString(s) - if err != nil { - panic(err) - } - return q -} - -func (q *BandwidthQuantity) Equal(u *BandwidthQuantity) bool { - if q == nil && u == nil { - return true - } - if q != nil && u != nil { - return q.i == u.i - } - return false -} - -func (q *BandwidthQuantity) String() string { - return q.s -} - -func (q *BandwidthQuantity) UnmarshalString(s string) error { - s = strings.TrimSpace(s) - if s == "" { - return nil - } - - var ( - base int64 - f float64 - err error - ) - if strings.HasSuffix(s, "MB") { - base = MB - fstr := strings.TrimSuffix(s, "MB") - f, err = strconv.ParseFloat(fstr, 64) - if err != nil { - return err - } - } else if strings.HasSuffix(s, "KB") { - base = KB - fstr := strings.TrimSuffix(s, "KB") - f, err = strconv.ParseFloat(fstr, 64) - if err != nil { - return err - } - } else { - return errors.New("unit not support") - } - - q.s = s - q.i = int64(f * float64(base)) - return nil -} - -func (q *BandwidthQuantity) UnmarshalJSON(b []byte) error { - if len(b) == 4 && string(b) == "null" { - return nil - } - - var str string - err := json.Unmarshal(b, &str) - if err != nil { - return err - } - - return q.UnmarshalString(str) -} - -func (q *BandwidthQuantity) MarshalJSON() ([]byte, error) { - return []byte("\"" + q.s + "\""), nil -} - -func (q *BandwidthQuantity) Bytes() int64 { - return q.i -} diff --git a/pkg/config/value.go b/pkg/config/value.go new file mode 100644 index 00000000..59584e35 --- /dev/null +++ b/pkg/config/value.go @@ -0,0 +1,78 @@ +// Copyright 2020 The frp Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "bytes" + "io/ioutil" + "os" + "strings" + "text/template" +) + +var ( + glbEnvs map[string]string +) + +func init() { + glbEnvs = make(map[string]string) + envs := os.Environ() + for _, env := range envs { + kv := strings.Split(env, "=") + if len(kv) != 2 { + continue + } + glbEnvs[kv[0]] = kv[1] + } +} + +type Values struct { + Envs map[string]string // environment vars +} + +func GetValues() *Values { + return &Values{ + Envs: glbEnvs, + } +} + +func RenderContent(in string) (out string, err error) { + tmpl, errRet := template.New("frp").Parse(in) + if errRet != nil { + err = errRet + return + } + + buffer := bytes.NewBufferString("") + v := GetValues() + err = tmpl.Execute(buffer, v) + if err != nil { + return + } + out = buffer.String() + return +} + +func GetRenderedConfFromFile(path string) (out string, err error) { + var b []byte + b, err = ioutil.ReadFile(path) + if err != nil { + return + } + content := string(b) + + out, err = RenderContent(content) + return +} diff --git a/pkg/config/visitor.go b/pkg/config/visitor.go index 3b5a951b..051a1618 100644 --- a/pkg/config/visitor.go +++ b/pkg/config/visitor.go @@ -21,7 +21,6 @@ import ( "gopkg.in/ini.v1" ) -// Visitor Conf Loader // DefaultVisitorConf creates a empty VisitorConf object by visitorType. // If visitorType doesn't exist, return nil. func DefaultVisitorConf(visitorType string) VisitorConf { @@ -59,111 +58,67 @@ func NewVisitorConfFromIni(prefix string, name string, section *ini.Section) (Vi } // Base -func (c *BaseVisitorConf) GetBaseInfo() *BaseVisitorConf { - return c +func (cfg *BaseVisitorConf) GetBaseInfo() *BaseVisitorConf { + return cfg } -func (c *BaseVisitorConf) compare(cmp *BaseVisitorConf) bool { - if c.ProxyName != cmp.ProxyName || - c.ProxyType != cmp.ProxyType || - c.UseEncryption != cmp.UseEncryption || - c.UseCompression != cmp.UseCompression || - c.Role != cmp.Role || - c.Sk != cmp.Sk || - c.ServerName != cmp.ServerName || - c.BindAddr != cmp.BindAddr || - c.BindPort != cmp.BindPort { +func (cfg *BaseVisitorConf) compare(cmp *BaseVisitorConf) bool { + if cfg.ProxyName != cmp.ProxyName || + cfg.ProxyType != cmp.ProxyType || + cfg.UseEncryption != cmp.UseEncryption || + cfg.UseCompression != cmp.UseCompression || + cfg.Role != cmp.Role || + cfg.Sk != cmp.Sk || + cfg.ServerName != cmp.ServerName || + cfg.BindAddr != cmp.BindAddr || + cfg.BindPort != cmp.BindPort { return false } return true } -func (c *BaseVisitorConf) check() (err error) { - if c.Role != "visitor" { +func (cfg *BaseVisitorConf) check() (err error) { + if cfg.Role != "visitor" { err = fmt.Errorf("invalid role") return } - if c.BindAddr == "" { + if cfg.BindAddr == "" { err = fmt.Errorf("bind_addr shouldn't be empty") return } - if c.BindPort <= 0 { + if cfg.BindPort <= 0 { err = fmt.Errorf("bind_port is required") return } return } -func (c *BaseVisitorConf) decorate(prefix string, name string, section *ini.Section) error { +func (cfg *BaseVisitorConf) decorate(prefix string, name string, section *ini.Section) error { // proxy name - c.ProxyName = prefix + name + cfg.ProxyName = prefix + name // server_name - c.ServerName = prefix + c.ServerName + cfg.ServerName = prefix + cfg.ServerName // bind_addr - if c.BindAddr == "" { - c.BindAddr = "127.0.0.1" + if cfg.BindAddr == "" { + cfg.BindAddr = "127.0.0.1" } return nil } -// STCP -var _ VisitorConf = &STCPVisitorConf{} - -func (c *STCPVisitorConf) Compare(conf VisitorConf) bool { - cmp, ok := conf.(*STCPVisitorConf) - if !ok { - return false - } - - if !c.BaseVisitorConf.compare(&cmp.BaseVisitorConf) { - return false - } - - // Add custom login equal, if exists - - return true -} - -func (c *STCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) - if err != nil { - return err - } - - err = c.BaseVisitorConf.decorate(prefix, name, section) - if err != nil { - return err - } - - // Add custom logic unmarshal, if exists - - return nil -} - -func (cfg *STCPVisitorConf) Check() error { - if err := cfg.BaseVisitorConf.check(); err != nil { - return err - } - - // Add custom logic validate, if exists - - return nil -} - // SUDP var _ VisitorConf = &SUDPVisitorConf{} -func (c *SUDPVisitorConf) Compare(conf VisitorConf) bool { - cmp, ok := conf.(*SUDPVisitorConf) +func (cfg *SUDPVisitorConf) Compare(cmp VisitorConf) bool { + cmpConf, ok := cmp.(*SUDPVisitorConf) if !ok { return false } - if !c.BaseVisitorConf.compare(&cmp.BaseVisitorConf) { + if !cfg.BaseVisitorConf.compare(&cmpConf.BaseVisitorConf) { return false } @@ -172,13 +127,13 @@ func (c *SUDPVisitorConf) Compare(conf VisitorConf) bool { return true } -func (c *SUDPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) +func (cfg *SUDPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) if err != nil { return err } - err = c.BaseVisitorConf.decorate(prefix, name, section) + err = cfg.BaseVisitorConf.decorate(prefix, name, section) if err != nil { return err } @@ -188,26 +143,70 @@ func (c *SUDPVisitorConf) UnmarshalFromIni(prefix string, name string, section * return nil } -func (cfg *SUDPVisitorConf) Check() error { - if err := cfg.BaseVisitorConf.check(); err != nil { - return err +func (cfg *SUDPVisitorConf) Check() (err error) { + if err = cfg.BaseVisitorConf.check(); err != nil { + return } // Add custom logic validate, if exists + return +} + +// STCP +var _ VisitorConf = &STCPVisitorConf{} + +func (cfg *STCPVisitorConf) Compare(cmp VisitorConf) bool { + cmpConf, ok := cmp.(*STCPVisitorConf) + if !ok { + return false + } + + if !cfg.BaseVisitorConf.compare(&cmpConf.BaseVisitorConf) { + return false + } + + // Add custom login equal, if exists + + return true +} + +func (cfg *STCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) + if err != nil { + return err + } + + err = cfg.BaseVisitorConf.decorate(prefix, name, section) + if err != nil { + return err + } + + // Add custom logic unmarshal, if exists + return nil } +func (cfg *STCPVisitorConf) Check() (err error) { + if err = cfg.BaseVisitorConf.check(); err != nil { + return + } + + // Add custom logic validate, if exists + + return +} + // XTCP var _ VisitorConf = &XTCPVisitorConf{} -func (c *XTCPVisitorConf) Compare(conf VisitorConf) bool { - cmp, ok := conf.(*XTCPVisitorConf) +func (cfg *XTCPVisitorConf) Compare(cmp VisitorConf) bool { + cmpConf, ok := cmp.(*XTCPVisitorConf) if !ok { return false } - if !c.BaseVisitorConf.compare(&cmp.BaseVisitorConf) { + if !cfg.BaseVisitorConf.compare(&cmpConf.BaseVisitorConf) { return false } @@ -216,13 +215,13 @@ func (c *XTCPVisitorConf) Compare(conf VisitorConf) bool { return true } -func (c *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { - err := section.MapTo(c) +func (cfg *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error { + err := section.MapTo(cfg) if err != nil { return err } - err = c.BaseVisitorConf.decorate(prefix, name, section) + err = cfg.BaseVisitorConf.decorate(prefix, name, section) if err != nil { return err } @@ -232,12 +231,12 @@ func (c *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section * return nil } -func (cfg *XTCPVisitorConf) Check() error { - if err := cfg.BaseVisitorConf.check(); err != nil { - return err +func (cfg *XTCPVisitorConf) Check() (err error) { + if err = cfg.BaseVisitorConf.check(); err != nil { + return } // Add custom logic validate, if exists - return nil + return } diff --git a/pkg/config/visitor_test.go b/pkg/config/visitor_test.go index 4d1f9830..193cb163 100644 --- a/pkg/config/visitor_test.go +++ b/pkg/config/visitor_test.go @@ -1,3 +1,17 @@ +// Copyright 2020 The frp Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package config import ( diff --git a/server/dashboard_api.go b/server/dashboard_api.go index b8d1c6fc..d3100c84 100644 --- a/server/dashboard_api.go +++ b/server/dashboard_api.go @@ -98,7 +98,7 @@ type TCPOutConf struct { type TCPMuxOutConf struct { BaseOutConf - config.DomainSpec + config.DomainConf Multiplexer string `json:"multiplexer"` } @@ -109,14 +109,14 @@ type UDPOutConf struct { type HTTPOutConf struct { BaseOutConf - config.DomainSpec + config.DomainConf Locations []string `json:"locations"` HostHeaderRewrite string `json:"host_header_rewrite"` } type HTTPSOutConf struct { BaseOutConf - config.DomainSpec + config.DomainConf } type STCPOutConf struct {