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 90456857..b3e3f81a 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 4d7205bb..af61b395 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 6a12b8c1..30992f9a 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 bc230f40..0c43740f 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 fb230b3e..1d0d8786 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 0b29e481..b02e5291 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 356b6bf5..266ab49d 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 6eb3688c..773aa115 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 6e682e64..081102cb 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 6fc06152..7d5fbe8b 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 46118c3e..f3514754 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 157206f3..82a906bd 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 8f55ce13..783ec29f 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 610fd73a..1a04fbf3 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 76a2a3c8..c2ccd2b8 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 f2d9d488..0d73c763 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 5ba944e7..558294da 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 ecd2471d..00000000 --- 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 7b7040ee..5d9d127f 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 (