From 666f122a72e6a1fb3bbc42639577f09607c6c443 Mon Sep 17 00:00:00 2001 From: Tyler Compton Date: Tue, 20 Aug 2019 13:53:27 -0700 Subject: [PATCH] Pass client configuration as an argument The ClientCommonConf, configuration file path, and server UDP port are now passed around as arguments instead of being shared between components as global variables. This allows for multiple clients to exist in the same process, and allows client.Session to be used as a library more easily. --- client/admin.go | 3 +- client/admin_api.go | 37 +++++++++--------- client/control.go | 31 +++++++++------ client/proxy/proxy.go | 23 ++++++----- client/proxy/proxy_manager.go | 21 ++++++---- client/proxy/proxy_wrapper.go | 4 +- client/service.go | 43 ++++++++++++--------- client/visitor.go | 5 +-- cmd/frpc/sub/http.go | 4 +- cmd/frpc/sub/https.go | 4 +- cmd/frpc/sub/reload.go | 15 ++++---- cmd/frpc/sub/root.go | 70 +++++++++++++++++----------------- cmd/frpc/sub/status.go | 15 ++++---- cmd/frpc/sub/stcp.go | 4 +- cmd/frpc/sub/tcp.go | 4 +- cmd/frpc/sub/udp.go | 4 +- cmd/frpc/sub/xtcp.go | 4 +- g/g.go | 22 ----------- models/config/client_common.go | 13 +++---- 19 files changed, 162 insertions(+), 164 deletions(-) delete mode 100644 g/g.go diff --git a/client/admin.go b/client/admin.go index 9045685..b3e3f81 100644 --- a/client/admin.go +++ b/client/admin.go @@ -21,7 +21,6 @@ import ( "time" "github.com/fatedier/frp/assets" - "github.com/fatedier/frp/g" frpNet "github.com/fatedier/frp/utils/net" "github.com/gorilla/mux" @@ -36,7 +35,7 @@ func (svr *Service) RunAdminServer(addr string, port int) (err error) { // url router router := mux.NewRouter() - user, passwd := g.GlbClientCfg.AdminUser, g.GlbClientCfg.AdminPwd + user, passwd := svr.cfg.AdminUser, svr.cfg.AdminPwd router.Use(frpNet.NewHttpAuthMiddleware(user, passwd).Middleware) // api, see dashboard_api.go diff --git a/client/admin_api.go b/client/admin_api.go index 4d7205b..af61b39 100644 --- a/client/admin_api.go +++ b/client/admin_api.go @@ -23,7 +23,6 @@ import ( "strings" "github.com/fatedier/frp/client/proxy" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/utils/log" ) @@ -47,7 +46,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) { } }() - content, err := config.GetRenderedConfFromFile(g.GlbClientCfg.CfgFile) + content, err := config.GetRenderedConfFromFile(svr.cfgFile) if err != nil { res.Code = 400 res.Msg = err.Error() @@ -55,7 +54,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) { return } - newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content) + newCommonCfg, err := config.UnmarshalClientConfFromIni(content) if err != nil { res.Code = 400 res.Msg = err.Error() @@ -63,7 +62,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) { return } - pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.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() @@ -107,7 +106,7 @@ func (a ByProxyStatusResp) Len() int { return len(a) } func (a ByProxyStatusResp) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByProxyStatusResp) Less(i, j int) bool { return strings.Compare(a[i].Name, a[j].Name) < 0 } -func NewProxyStatusResp(status *proxy.ProxyStatus) ProxyStatusResp { +func NewProxyStatusResp(status *proxy.ProxyStatus, serverAddr string) ProxyStatusResp { psr := ProxyStatusResp{ Name: status.Name, Type: status.Type, @@ -121,18 +120,18 @@ func NewProxyStatusResp(status *proxy.ProxyStatus) ProxyStatusResp { } psr.Plugin = cfg.Plugin if status.Err != "" { - psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort) + psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort) } else { - psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr + psr.RemoteAddr = serverAddr + status.RemoteAddr } case *config.UdpProxyConf: if cfg.LocalPort != 0 { psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort) } if status.Err != "" { - psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort) + psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort) } else { - psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr + psr.RemoteAddr = serverAddr + status.RemoteAddr } case *config.HttpProxyConf: if cfg.LocalPort != 0 { @@ -184,17 +183,17 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) { for _, status := range ps { switch status.Type { case "tcp": - res.Tcp = append(res.Tcp, NewProxyStatusResp(status)) + res.Tcp = append(res.Tcp, NewProxyStatusResp(status, svr.cfg.ServerAddr)) case "udp": - res.Udp = append(res.Udp, NewProxyStatusResp(status)) + res.Udp = append(res.Udp, NewProxyStatusResp(status, svr.cfg.ServerAddr)) case "http": - res.Http = append(res.Http, NewProxyStatusResp(status)) + res.Http = append(res.Http, NewProxyStatusResp(status, svr.cfg.ServerAddr)) case "https": - res.Https = append(res.Https, NewProxyStatusResp(status)) + res.Https = append(res.Https, NewProxyStatusResp(status, svr.cfg.ServerAddr)) case "stcp": - res.Stcp = append(res.Stcp, NewProxyStatusResp(status)) + res.Stcp = append(res.Stcp, NewProxyStatusResp(status, svr.cfg.ServerAddr)) case "xtcp": - res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status)) + res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status, svr.cfg.ServerAddr)) } } sort.Sort(ByProxyStatusResp(res.Tcp)) @@ -219,14 +218,14 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, r *http.Request) { } }() - if g.GlbClientCfg.CfgFile == "" { + if svr.cfgFile == "" { res.Code = 400 res.Msg = "frpc has no config file path" log.Warn("%s", res.Msg) return } - content, err := config.GetRenderedConfFromFile(g.GlbClientCfg.CfgFile) + content, err := config.GetRenderedConfFromFile(svr.cfgFile) if err != nil { res.Code = 400 res.Msg = err.Error() @@ -277,7 +276,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) { // get token from origin content token := "" - b, err := ioutil.ReadFile(g.GlbClientCfg.CfgFile) + b, err := ioutil.ReadFile(svr.cfgFile) if err != nil { res.Code = 400 res.Msg = err.Error() @@ -316,7 +315,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) { } content = strings.Join(newRows, "\n") - err = ioutil.WriteFile(g.GlbClientCfg.CfgFile, []byte(content), 0644) + err = ioutil.WriteFile(svr.cfgFile, []byte(content), 0644) if err != nil { res.Code = 500 res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err) diff --git a/client/control.go b/client/control.go index 6a12b8c..30992f9 100644 --- a/client/control.go +++ b/client/control.go @@ -23,7 +23,6 @@ import ( "time" "github.com/fatedier/frp/client/proxy" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/utils/log" @@ -65,16 +64,24 @@ type Control struct { // last time got the Pong message lastPong time.Time + // The client configuration + clientCfg config.ClientCommonConf + readerShutdown *shutdown.Shutdown writerShutdown *shutdown.Shutdown msgHandlerShutdown *shutdown.Shutdown + // The UDP port that the server is listening on + serverUDPPort int + mu sync.RWMutex log.Logger } -func NewControl(runId string, conn frpNet.Conn, session *fmux.Session, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) *Control { +func NewControl(runId string, conn frpNet.Conn, session *fmux.Session, clientCfg config.ClientCommonConf, + pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, serverUDPPort int) *Control { + ctl := &Control{ runId: runId, conn: conn, @@ -84,12 +91,14 @@ func NewControl(runId string, conn frpNet.Conn, session *fmux.Session, pxyCfgs m readCh: make(chan msg.Message, 100), closedCh: make(chan struct{}), closedDoneCh: make(chan struct{}), + clientCfg: clientCfg, readerShutdown: shutdown.New(), writerShutdown: shutdown.New(), msgHandlerShutdown: shutdown.New(), + serverUDPPort: serverUDPPort, Logger: log.NewPrefixLogger(""), } - ctl.pm = proxy.NewProxyManager(ctl.sendCh, runId) + ctl.pm = proxy.NewProxyManager(ctl.sendCh, runId, clientCfg, serverUDPPort) ctl.vm = NewVisitorManager(ctl) ctl.vm.Reload(visitorCfgs) @@ -161,7 +170,7 @@ func (ctl *Control) ClosedDoneCh() <-chan struct{} { // connectServer return a new connection to frps func (ctl *Control) connectServer() (conn frpNet.Conn, err error) { - if g.GlbClientCfg.TcpMux { + if ctl.clientCfg.TcpMux { stream, errRet := ctl.session.OpenStream() if errRet != nil { err = errRet @@ -171,13 +180,13 @@ func (ctl *Control) connectServer() (conn frpNet.Conn, err error) { conn = frpNet.WrapConn(stream) } else { var tlsConfig *tls.Config - if g.GlbClientCfg.TLSEnable { + if ctl.clientCfg.TLSEnable { tlsConfig = &tls.Config{ InsecureSkipVerify: true, } } - conn, err = frpNet.ConnectServerByProxyWithTLS(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol, - fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort), tlsConfig) + conn, err = frpNet.ConnectServerByProxyWithTLS(ctl.clientCfg.HttpProxy, ctl.clientCfg.Protocol, + fmt.Sprintf("%s:%d", ctl.clientCfg.ServerAddr, ctl.clientCfg.ServerPort), tlsConfig) if err != nil { ctl.Warn("start new connection to server error: %v", err) return @@ -197,7 +206,7 @@ func (ctl *Control) reader() { defer ctl.readerShutdown.Done() defer close(ctl.closedCh) - encReader := crypto.NewReader(ctl.conn, []byte(g.GlbClientCfg.Token)) + encReader := crypto.NewReader(ctl.conn, []byte(ctl.clientCfg.Token)) for { if m, err := msg.ReadMsg(encReader); err != nil { if err == io.EOF { @@ -217,7 +226,7 @@ func (ctl *Control) reader() { // writer writes messages got from sendCh to frps func (ctl *Control) writer() { defer ctl.writerShutdown.Done() - encWriter, err := crypto.NewWriter(ctl.conn, []byte(g.GlbClientCfg.Token)) + encWriter, err := crypto.NewWriter(ctl.conn, []byte(ctl.clientCfg.Token)) if err != nil { ctl.conn.Error("crypto new writer error: %v", err) ctl.conn.Close() @@ -246,7 +255,7 @@ func (ctl *Control) msgHandler() { }() defer ctl.msgHandlerShutdown.Done() - hbSend := time.NewTicker(time.Duration(g.GlbClientCfg.HeartBeatInterval) * time.Second) + hbSend := time.NewTicker(time.Duration(ctl.clientCfg.HeartBeatInterval) * time.Second) defer hbSend.Stop() hbCheck := time.NewTicker(time.Second) defer hbCheck.Stop() @@ -260,7 +269,7 @@ func (ctl *Control) msgHandler() { ctl.Debug("send heartbeat to server") ctl.sendCh <- &msg.Ping{} case <-hbCheck.C: - if time.Since(ctl.lastPong) > time.Duration(g.GlbClientCfg.HeartBeatTimeout)*time.Second { + if time.Since(ctl.lastPong) > time.Duration(ctl.clientCfg.HeartBeatTimeout)*time.Second { ctl.Warn("heartbeat timeout") // let reader() stop ctl.conn.Close() diff --git a/client/proxy/proxy.go b/client/proxy/proxy.go index bc230f4..0c43740 100644 --- a/client/proxy/proxy.go +++ b/client/proxy/proxy.go @@ -25,7 +25,6 @@ import ( "sync" "time" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/plugin" @@ -51,9 +50,11 @@ type Proxy interface { log.Logger } -func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) { +func NewProxy(pxyConf config.ProxyConf, clientCfg config.ClientCommonConf, serverUDPPort int) (pxy Proxy) { baseProxy := BaseProxy{ - Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName), + Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName), + clientCfg: clientCfg, + serverUDPPort: serverUDPPort, } switch cfg := pxyConf.(type) { case *config.TcpProxyConf: @@ -91,8 +92,10 @@ func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) { } type BaseProxy struct { - closed bool - mu sync.RWMutex + closed bool + mu sync.RWMutex + clientCfg config.ClientCommonConf + serverUDPPort int log.Logger } @@ -122,7 +125,7 @@ func (pxy *TcpProxy) Close() { func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(g.GlbClientCfg.Token), m) + []byte(pxy.clientCfg.Token), m) } // HTTP @@ -151,7 +154,7 @@ func (pxy *HttpProxy) Close() { func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(g.GlbClientCfg.Token), m) + []byte(pxy.clientCfg.Token), m) } // HTTPS @@ -180,7 +183,7 @@ func (pxy *HttpsProxy) Close() { func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(g.GlbClientCfg.Token), m) + []byte(pxy.clientCfg.Token), m) } // STCP @@ -209,7 +212,7 @@ func (pxy *StcpProxy) Close() { func (pxy *StcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(g.GlbClientCfg.Token), m) + []byte(pxy.clientCfg.Token), m) } // XTCP @@ -250,7 +253,7 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) { Sid: natHoleSidMsg.Sid, } raddr, _ := net.ResolveUDPAddr("udp", - fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerUdpPort)) + fmt.Sprintf("%s:%d", pxy.clientCfg.ServerAddr, pxy.serverUDPPort)) clientConn, err := net.DialUDP("udp", nil, raddr) defer clientConn.Close() diff --git a/client/proxy/proxy_manager.go b/client/proxy/proxy_manager.go index fb230b3..1d0d878 100644 --- a/client/proxy/proxy_manager.go +++ b/client/proxy/proxy_manager.go @@ -20,17 +20,24 @@ type ProxyManager struct { closed bool mu sync.RWMutex + clientCfg config.ClientCommonConf + + // The UDP port that the server is listening on + serverUDPPort int + logPrefix string log.Logger } -func NewProxyManager(msgSendCh chan (msg.Message), logPrefix string) *ProxyManager { +func NewProxyManager(msgSendCh chan (msg.Message), logPrefix string, clientCfg config.ClientCommonConf, serverUDPPort int) *ProxyManager { return &ProxyManager{ - proxies: make(map[string]*ProxyWrapper), - sendCh: msgSendCh, - closed: false, - logPrefix: logPrefix, - Logger: log.NewPrefixLogger(logPrefix), + proxies: make(map[string]*ProxyWrapper), + sendCh: msgSendCh, + closed: false, + clientCfg: clientCfg, + serverUDPPort: serverUDPPort, + logPrefix: logPrefix, + Logger: log.NewPrefixLogger(logPrefix), } } @@ -126,7 +133,7 @@ func (pm *ProxyManager) Reload(pxyCfgs map[string]config.ProxyConf) { addPxyNames := make([]string, 0) for name, cfg := range pxyCfgs { if _, ok := pm.proxies[name]; !ok { - pxy := NewProxyWrapper(cfg, pm.HandleEvent, pm.logPrefix) + pxy := NewProxyWrapper(cfg, pm.clientCfg, pm.HandleEvent, pm.logPrefix, pm.serverUDPPort) pm.proxies[name] = pxy addPxyNames = append(addPxyNames, name) diff --git a/client/proxy/proxy_wrapper.go b/client/proxy/proxy_wrapper.go index 0b29e48..b02e529 100644 --- a/client/proxy/proxy_wrapper.go +++ b/client/proxy/proxy_wrapper.go @@ -65,7 +65,7 @@ type ProxyWrapper struct { log.Logger } -func NewProxyWrapper(cfg config.ProxyConf, eventHandler event.EventHandler, logPrefix string) *ProxyWrapper { +func NewProxyWrapper(cfg config.ProxyConf, clientCfg config.ClientCommonConf, eventHandler event.EventHandler, logPrefix string, serverUDPPort int) *ProxyWrapper { baseInfo := cfg.GetBaseInfo() pw := &ProxyWrapper{ ProxyStatus: ProxyStatus{ @@ -90,7 +90,7 @@ func NewProxyWrapper(cfg config.ProxyConf, eventHandler event.EventHandler, logP pw.Trace("enable health check monitor") } - pw.pxy = NewProxy(pw.Cfg) + pw.pxy = NewProxy(pw.Cfg, clientCfg, serverUDPPort) return pw } diff --git a/client/service.go b/client/service.go index 356b6bf..266ab49 100644 --- a/client/service.go +++ b/client/service.go @@ -24,7 +24,6 @@ import ( "time" "github.com/fatedier/frp/assets" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/utils/log" @@ -43,16 +42,26 @@ type Service struct { ctl *Control ctlMu sync.RWMutex + cfg config.ClientCommonConf pxyCfgs map[string]config.ProxyConf visitorCfgs map[string]config.VisitorConf cfgMu sync.RWMutex + // The configuration file used to initialize this client, or an empty + // string if no configuration file was used. + cfgFile string + + // This is configured by the login response from frps + serverUDPPort int + exit uint32 // 0 means not exit closedCh chan int } -func NewService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (svr *Service, err error) { +func NewService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (svr *Service, err error) { svr = &Service{ + cfg: cfg, + cfgFile: cfgFile, pxyCfgs: pxyCfgs, visitorCfgs: visitorCfgs, exit: 0, @@ -76,14 +85,14 @@ func (svr *Service) Run() error { // if login_fail_exit is true, just exit this program // otherwise sleep a while and try again to connect to server - if g.GlbClientCfg.LoginFailExit { + if svr.cfg.LoginFailExit { return err } else { time.Sleep(10 * time.Second) } } else { // login success - ctl := NewControl(svr.runId, conn, session, svr.pxyCfgs, svr.visitorCfgs) + ctl := NewControl(svr.runId, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort) ctl.Run() svr.ctlMu.Lock() svr.ctl = ctl @@ -94,18 +103,18 @@ func (svr *Service) Run() error { go svr.keepControllerWorking() - if g.GlbClientCfg.AdminPort != 0 { + if svr.cfg.AdminPort != 0 { // Init admin server assets - err := assets.Load(g.GlbClientCfg.AssetsDir) + err := assets.Load(svr.cfg.AssetsDir) if err != nil { return fmt.Errorf("Load assets error: %v", err) } - err = svr.RunAdminServer(g.GlbClientCfg.AdminAddr, g.GlbClientCfg.AdminPort) + err = svr.RunAdminServer(svr.cfg.AdminAddr, svr.cfg.AdminPort) if err != nil { log.Warn("run admin server error: %v", err) } - log.Info("admin server listen on %s:%d", g.GlbClientCfg.AdminAddr, g.GlbClientCfg.AdminPort) + log.Info("admin server listen on %s:%d", svr.cfg.AdminAddr, svr.cfg.AdminPort) } <-svr.closedCh @@ -137,7 +146,7 @@ func (svr *Service) keepControllerWorking() { // reconnect success, init delayTime delayTime = time.Second - ctl := NewControl(svr.runId, conn, session, svr.pxyCfgs, svr.visitorCfgs) + ctl := NewControl(svr.runId, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort) ctl.Run() svr.ctlMu.Lock() svr.ctl = ctl @@ -152,13 +161,13 @@ func (svr *Service) keepControllerWorking() { // session: if it's not nil, using tcp mux func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error) { var tlsConfig *tls.Config - if g.GlbClientCfg.TLSEnable { + if svr.cfg.TLSEnable { tlsConfig = &tls.Config{ InsecureSkipVerify: true, } } - conn, err = frpNet.ConnectServerByProxyWithTLS(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol, - fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort), tlsConfig) + conn, err = frpNet.ConnectServerByProxyWithTLS(svr.cfg.HttpProxy, svr.cfg.Protocol, + fmt.Sprintf("%s:%d", svr.cfg.ServerAddr, svr.cfg.ServerPort), tlsConfig) if err != nil { return } @@ -172,7 +181,7 @@ func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error) } }() - if g.GlbClientCfg.TcpMux { + if svr.cfg.TcpMux { fmuxCfg := fmux.DefaultConfig() fmuxCfg.KeepAliveInterval = 20 * time.Second fmuxCfg.LogOutput = ioutil.Discard @@ -193,10 +202,10 @@ func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error) loginMsg := &msg.Login{ Arch: runtime.GOARCH, Os: runtime.GOOS, - PoolCount: g.GlbClientCfg.PoolCount, - User: g.GlbClientCfg.User, + PoolCount: svr.cfg.PoolCount, + User: svr.cfg.User, Version: version.Full(), - PrivilegeKey: util.GetAuthKey(g.GlbClientCfg.Token, now), + PrivilegeKey: util.GetAuthKey(svr.cfg.Token, now), Timestamp: now, RunId: svr.runId, } @@ -219,7 +228,7 @@ func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error) } svr.runId = loginRespMsg.RunId - g.GlbClientCfg.ServerUdpPort = loginRespMsg.ServerUdpPort + svr.serverUDPPort = loginRespMsg.ServerUdpPort log.Info("login to server success, get run id [%s], server udp port [%d]", loginRespMsg.RunId, loginRespMsg.ServerUdpPort) return } diff --git a/client/visitor.go b/client/visitor.go index 6eb3688..773aa11 100644 --- a/client/visitor.go +++ b/client/visitor.go @@ -23,7 +23,6 @@ import ( "sync" "time" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/utils/log" @@ -193,13 +192,13 @@ func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) { defer userConn.Close() sv.Debug("get a new xtcp user connection") - if g.GlbClientCfg.ServerUdpPort == 0 { + if sv.ctl.serverUDPPort == 0 { sv.Error("xtcp is not supported by server") return } raddr, err := net.ResolveUDPAddr("udp", - fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerUdpPort)) + fmt.Sprintf("%s:%d", sv.ctl.clientCfg.ServerAddr, sv.ctl.serverUDPPort)) if err != nil { sv.Error("resolve server UDP addr error") return diff --git a/cmd/frpc/sub/http.go b/cmd/frpc/sub/http.go index 6e682e6..081102c 100644 --- a/cmd/frpc/sub/http.go +++ b/cmd/frpc/sub/http.go @@ -54,7 +54,7 @@ var httpCmd = &cobra.Command{ Use: "http", Short: "Run frpc with a single http proxy", RunE: func(cmd *cobra.Command, args []string) error { - err := parseClientCommonCfg(CfgFileTypeCmd, "") + clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "") if err != nil { fmt.Println(err) os.Exit(1) @@ -87,7 +87,7 @@ var httpCmd = &cobra.Command{ proxyConfs := map[string]config.ProxyConf{ cfg.ProxyName: cfg, } - err = startService(proxyConfs, nil) + err = startService(clientCfg, proxyConfs, nil, "") if err != nil { fmt.Println(err) os.Exit(1) diff --git a/cmd/frpc/sub/https.go b/cmd/frpc/sub/https.go index 6fc0615..7d5fbe8 100644 --- a/cmd/frpc/sub/https.go +++ b/cmd/frpc/sub/https.go @@ -50,7 +50,7 @@ var httpsCmd = &cobra.Command{ Use: "https", Short: "Run frpc with a single https proxy", RunE: func(cmd *cobra.Command, args []string) error { - err := parseClientCommonCfg(CfgFileTypeCmd, "") + clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "") if err != nil { fmt.Println(err) os.Exit(1) @@ -79,7 +79,7 @@ var httpsCmd = &cobra.Command{ proxyConfs := map[string]config.ProxyConf{ cfg.ProxyName: cfg, } - err = startService(proxyConfs, nil) + err = startService(clientCfg, proxyConfs, nil, "") if err != nil { fmt.Println(err) os.Exit(1) diff --git a/cmd/frpc/sub/reload.go b/cmd/frpc/sub/reload.go index 46118c3..f351475 100644 --- a/cmd/frpc/sub/reload.go +++ b/cmd/frpc/sub/reload.go @@ -24,7 +24,6 @@ import ( "github.com/spf13/cobra" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" ) @@ -42,13 +41,13 @@ var reloadCmd = &cobra.Command{ os.Exit(1) } - err = parseClientCommonCfg(CfgFileTypeIni, iniContent) + clientCfg, err := parseClientCommonCfg(CfgFileTypeIni, iniContent) if err != nil { fmt.Println(err) os.Exit(1) } - err = reload() + err = reload(clientCfg) if err != nil { fmt.Printf("frpc reload error: %v\n", err) os.Exit(1) @@ -58,19 +57,19 @@ var reloadCmd = &cobra.Command{ }, } -func reload() error { - if g.GlbClientCfg.AdminPort == 0 { +func reload(clientCfg config.ClientCommonConf) error { + if clientCfg.AdminPort == 0 { return fmt.Errorf("admin_port shoud be set if you want to use reload feature") } req, err := http.NewRequest("GET", "http://"+ - g.GlbClientCfg.AdminAddr+":"+fmt.Sprintf("%d", g.GlbClientCfg.AdminPort)+"/api/reload", nil) + clientCfg.AdminAddr+":"+fmt.Sprintf("%d", clientCfg.AdminPort)+"/api/reload", nil) if err != nil { return err } - authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(g.GlbClientCfg.AdminUser+":"+ - g.GlbClientCfg.AdminPwd)) + authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(clientCfg.AdminUser+":"+ + clientCfg.AdminPwd)) req.Header.Add("Authorization", authStr) resp, err := http.DefaultClient.Do(req) diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go index 157206f..82a906b 100644 --- a/cmd/frpc/sub/root.go +++ b/cmd/frpc/sub/root.go @@ -28,7 +28,6 @@ import ( "github.com/spf13/cobra" "github.com/fatedier/frp/client" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/version" @@ -114,60 +113,62 @@ func handleSignal(svr *client.Service) { close(kcpDoneCh) } -func parseClientCommonCfg(fileType int, content string) (err error) { +func parseClientCommonCfg(fileType int, content string) (cfg config.ClientCommonConf, err error) { if fileType == CfgFileTypeIni { - err = parseClientCommonCfgFromIni(content) + cfg, err = parseClientCommonCfgFromIni(content) } else if fileType == CfgFileTypeCmd { - err = parseClientCommonCfgFromCmd() + cfg, err = parseClientCommonCfgFromCmd() } if err != nil { return } - err = g.GlbClientCfg.ClientCommonConf.Check() + err = cfg.Check() if err != nil { return } return } -func parseClientCommonCfgFromIni(content string) (err error) { - cfg, err := config.UnmarshalClientConfFromIni(&g.GlbClientCfg.ClientCommonConf, content) +func parseClientCommonCfgFromIni(content string) (config.ClientCommonConf, error) { + cfg, err := config.UnmarshalClientConfFromIni(content) if err != nil { - return err + return config.ClientCommonConf{}, err } - g.GlbClientCfg.ClientCommonConf = *cfg - return + return cfg, err } -func parseClientCommonCfgFromCmd() (err error) { +func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) { + cfg = config.GetDefaultClientConf() + strs := strings.Split(serverAddr, ":") if len(strs) < 2 { err = fmt.Errorf("invalid server_addr") return } if strs[0] != "" { - g.GlbClientCfg.ServerAddr = strs[0] + cfg.ServerAddr = strs[0] } - g.GlbClientCfg.ServerPort, err = strconv.Atoi(strs[1]) + cfg.ServerPort, err = strconv.Atoi(strs[1]) if err != nil { err = fmt.Errorf("invalid server_addr") return } - g.GlbClientCfg.User = user - g.GlbClientCfg.Protocol = protocol - g.GlbClientCfg.Token = token - g.GlbClientCfg.LogLevel = logLevel - g.GlbClientCfg.LogFile = logFile - g.GlbClientCfg.LogMaxDays = int64(logMaxDays) + cfg.User = user + cfg.Protocol = protocol + cfg.Token = token + cfg.LogLevel = logLevel + cfg.LogFile = logFile + cfg.LogMaxDays = int64(logMaxDays) if logFile == "console" { - g.GlbClientCfg.LogWay = "console" + cfg.LogWay = "console" } else { - g.GlbClientCfg.LogWay = "file" + cfg.LogWay = "file" } - g.GlbClientCfg.DisableLogColor = disableLogColor - return nil + cfg.DisableLogColor = disableLogColor + + return } func runClient(cfgFilePath string) (err error) { @@ -176,28 +177,27 @@ func runClient(cfgFilePath string) (err error) { if err != nil { return } - g.GlbClientCfg.CfgFile = cfgFilePath - err = parseClientCommonCfg(CfgFileTypeIni, content) + cfg, err := parseClientCommonCfg(CfgFileTypeIni, content) if err != nil { return } - pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.User, content, g.GlbClientCfg.Start) + pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(cfg.User, content, cfg.Start) if err != nil { return err } - err = startService(pxyCfgs, visitorCfgs) + err = startService(cfg, pxyCfgs, visitorCfgs, cfgFilePath) return } -func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (err error) { - log.InitLog(g.GlbClientCfg.LogWay, g.GlbClientCfg.LogFile, g.GlbClientCfg.LogLevel, - g.GlbClientCfg.LogMaxDays, g.GlbClientCfg.DisableLogColor) +func startService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (err error) { + log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel, + cfg.LogMaxDays, cfg.DisableLogColor) - if g.GlbClientCfg.DnsServer != "" { - s := g.GlbClientCfg.DnsServer + if cfg.DnsServer != "" { + s := cfg.DnsServer if !strings.Contains(s, ":") { s += ":53" } @@ -209,19 +209,19 @@ func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]co }, } } - svr, errRet := client.NewService(pxyCfgs, visitorCfgs) + svr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, cfgFile) if errRet != nil { err = errRet return } // Capture the exit signal if we use kcp. - if g.GlbClientCfg.Protocol == "kcp" { + if cfg.Protocol == "kcp" { go handleSignal(svr) } err = svr.Run() - if g.GlbClientCfg.Protocol == "kcp" { + if cfg.Protocol == "kcp" { <-kcpDoneCh } return diff --git a/cmd/frpc/sub/status.go b/cmd/frpc/sub/status.go index 8f55ce1..783ec29 100644 --- a/cmd/frpc/sub/status.go +++ b/cmd/frpc/sub/status.go @@ -27,7 +27,6 @@ import ( "github.com/spf13/cobra" "github.com/fatedier/frp/client" - "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" ) @@ -45,13 +44,13 @@ var statusCmd = &cobra.Command{ os.Exit(1) } - err = parseClientCommonCfg(CfgFileTypeIni, iniContent) + clientCfg, err := parseClientCommonCfg(CfgFileTypeIni, iniContent) if err != nil { fmt.Println(err) os.Exit(1) } - err = status() + err = status(clientCfg) if err != nil { fmt.Printf("frpc get status error: %v\n", err) os.Exit(1) @@ -60,19 +59,19 @@ var statusCmd = &cobra.Command{ }, } -func status() error { - if g.GlbClientCfg.AdminPort == 0 { +func status(clientCfg config.ClientCommonConf) error { + if clientCfg.AdminPort == 0 { return fmt.Errorf("admin_port shoud be set if you want to get proxy status") } req, err := http.NewRequest("GET", "http://"+ - g.GlbClientCfg.AdminAddr+":"+fmt.Sprintf("%d", g.GlbClientCfg.AdminPort)+"/api/status", nil) + clientCfg.AdminAddr+":"+fmt.Sprintf("%d", clientCfg.AdminPort)+"/api/status", nil) if err != nil { return err } - authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(g.GlbClientCfg.AdminUser+":"+ - g.GlbClientCfg.AdminPwd)) + authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(clientCfg.AdminUser+":"+ + clientCfg.AdminPwd)) req.Header.Add("Authorization", authStr) resp, err := http.DefaultClient.Do(req) diff --git a/cmd/frpc/sub/stcp.go b/cmd/frpc/sub/stcp.go index 610fd73..1a04fbf 100644 --- a/cmd/frpc/sub/stcp.go +++ b/cmd/frpc/sub/stcp.go @@ -52,7 +52,7 @@ var stcpCmd = &cobra.Command{ Use: "stcp", Short: "Run frpc with a single stcp proxy", RunE: func(cmd *cobra.Command, args []string) error { - err := parseClientCommonCfg(CfgFileTypeCmd, "") + clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "") if err != nil { fmt.Println(err) os.Exit(1) @@ -104,7 +104,7 @@ var stcpCmd = &cobra.Command{ os.Exit(1) } - err = startService(proxyConfs, visitorConfs) + err = startService(clientCfg, proxyConfs, visitorConfs, "") if err != nil { fmt.Println(err) os.Exit(1) diff --git a/cmd/frpc/sub/tcp.go b/cmd/frpc/sub/tcp.go index 76a2a3c..c2ccd2b 100644 --- a/cmd/frpc/sub/tcp.go +++ b/cmd/frpc/sub/tcp.go @@ -48,7 +48,7 @@ var tcpCmd = &cobra.Command{ Use: "tcp", Short: "Run frpc with a single tcp proxy", RunE: func(cmd *cobra.Command, args []string) error { - err := parseClientCommonCfg(CfgFileTypeCmd, "") + clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "") if err != nil { fmt.Println(err) os.Exit(1) @@ -76,7 +76,7 @@ var tcpCmd = &cobra.Command{ proxyConfs := map[string]config.ProxyConf{ cfg.ProxyName: cfg, } - err = startService(proxyConfs, nil) + err = startService(clientCfg, proxyConfs, nil, "") if err != nil { fmt.Println(err) os.Exit(1) diff --git a/cmd/frpc/sub/udp.go b/cmd/frpc/sub/udp.go index f2d9d48..0d73c76 100644 --- a/cmd/frpc/sub/udp.go +++ b/cmd/frpc/sub/udp.go @@ -48,7 +48,7 @@ var udpCmd = &cobra.Command{ Use: "udp", Short: "Run frpc with a single udp proxy", RunE: func(cmd *cobra.Command, args []string) error { - err := parseClientCommonCfg(CfgFileTypeCmd, "") + clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "") if err != nil { fmt.Println(err) os.Exit(1) @@ -76,7 +76,7 @@ var udpCmd = &cobra.Command{ proxyConfs := map[string]config.ProxyConf{ cfg.ProxyName: cfg, } - err = startService(proxyConfs, nil) + err = startService(clientCfg, proxyConfs, nil, "") if err != nil { fmt.Println(err) os.Exit(1) diff --git a/cmd/frpc/sub/xtcp.go b/cmd/frpc/sub/xtcp.go index 5ba944e..558294d 100644 --- a/cmd/frpc/sub/xtcp.go +++ b/cmd/frpc/sub/xtcp.go @@ -52,7 +52,7 @@ var xtcpCmd = &cobra.Command{ Use: "xtcp", Short: "Run frpc with a single xtcp proxy", RunE: func(cmd *cobra.Command, args []string) error { - err := parseClientCommonCfg(CfgFileTypeCmd, "") + clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "") if err != nil { fmt.Println(err) os.Exit(1) @@ -104,7 +104,7 @@ var xtcpCmd = &cobra.Command{ os.Exit(1) } - err = startService(proxyConfs, visitorConfs) + err = startService(clientCfg, proxyConfs, visitorConfs, "") if err != nil { fmt.Println(err) os.Exit(1) diff --git a/g/g.go b/g/g.go deleted file mode 100644 index ecd2471..0000000 --- a/g/g.go +++ /dev/null @@ -1,22 +0,0 @@ -package g - -import ( - "github.com/fatedier/frp/models/config" -) - -var ( - GlbClientCfg *ClientCfg -) - -func init() { - GlbClientCfg = &ClientCfg{ - ClientCommonConf: *config.GetDefaultClientConf(), - } -} - -type ClientCfg struct { - config.ClientCommonConf - - CfgFile string - ServerUdpPort int // this is configured by login response from frps -} diff --git a/models/config/client_common.go b/models/config/client_common.go index 7b7040e..5d9d127 100644 --- a/models/config/client_common.go +++ b/models/config/client_common.go @@ -51,8 +51,8 @@ type ClientCommonConf struct { HeartBeatTimeout int64 `json:"heartbeat_timeout"` } -func GetDefaultClientConf() *ClientCommonConf { - return &ClientCommonConf{ +func GetDefaultClientConf() ClientCommonConf { + return ClientCommonConf{ ServerAddr: "0.0.0.0", ServerPort: 7000, HttpProxy: os.Getenv("http_proxy"), @@ -80,16 +80,13 @@ func GetDefaultClientConf() *ClientCommonConf { } } -func UnmarshalClientConfFromIni(defaultCfg *ClientCommonConf, content string) (cfg *ClientCommonConf, err error) { - cfg = defaultCfg - if cfg == nil { - cfg = GetDefaultClientConf() - } +func UnmarshalClientConfFromIni(content string) (cfg ClientCommonConf, err error) { + cfg = GetDefaultClientConf() conf, err := ini.Load(strings.NewReader(content)) if err != nil { err = fmt.Errorf("parse ini conf file error: %v", err) - return nil, err + return ClientCommonConf{}, err } var (