Forráskód Böngészése

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.
Tyler Compton 5 éve
szülő
commit
666f122a72

+ 1 - 2
client/admin.go

@@ -21,7 +21,6 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/fatedier/frp/assets"
 	"github.com/fatedier/frp/assets"
-	"github.com/fatedier/frp/g"
 	frpNet "github.com/fatedier/frp/utils/net"
 	frpNet "github.com/fatedier/frp/utils/net"
 
 
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
@@ -36,7 +35,7 @@ func (svr *Service) RunAdminServer(addr string, port int) (err error) {
 	// url router
 	// url router
 	router := mux.NewRouter()
 	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)
 	router.Use(frpNet.NewHttpAuthMiddleware(user, passwd).Middleware)
 
 
 	// api, see dashboard_api.go
 	// api, see dashboard_api.go

+ 18 - 19
client/admin_api.go

@@ -23,7 +23,6 @@ import (
 	"strings"
 	"strings"
 
 
 	"github.com/fatedier/frp/client/proxy"
 	"github.com/fatedier/frp/client/proxy"
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/utils/log"
 	"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 {
 	if err != nil {
 		res.Code = 400
 		res.Code = 400
 		res.Msg = err.Error()
 		res.Msg = err.Error()
@@ -55,7 +54,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
-	newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content)
+	newCommonCfg, err := config.UnmarshalClientConfFromIni(content)
 	if err != nil {
 	if err != nil {
 		res.Code = 400
 		res.Code = 400
 		res.Msg = err.Error()
 		res.Msg = err.Error()
@@ -63,7 +62,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
 		return
 		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 {
 	if err != nil {
 		res.Code = 400
 		res.Code = 400
 		res.Msg = err.Error()
 		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) 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 (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{
 	psr := ProxyStatusResp{
 		Name:   status.Name,
 		Name:   status.Name,
 		Type:   status.Type,
 		Type:   status.Type,
@@ -121,18 +120,18 @@ func NewProxyStatusResp(status *proxy.ProxyStatus) ProxyStatusResp {
 		}
 		}
 		psr.Plugin = cfg.Plugin
 		psr.Plugin = cfg.Plugin
 		if status.Err != "" {
 		if status.Err != "" {
-			psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort)
+			psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
 		} else {
 		} else {
-			psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr
+			psr.RemoteAddr = serverAddr + status.RemoteAddr
 		}
 		}
 	case *config.UdpProxyConf:
 	case *config.UdpProxyConf:
 		if cfg.LocalPort != 0 {
 		if cfg.LocalPort != 0 {
 			psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
 			psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
 		}
 		}
 		if status.Err != "" {
 		if status.Err != "" {
-			psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort)
+			psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
 		} else {
 		} else {
-			psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr
+			psr.RemoteAddr = serverAddr + status.RemoteAddr
 		}
 		}
 	case *config.HttpProxyConf:
 	case *config.HttpProxyConf:
 		if cfg.LocalPort != 0 {
 		if cfg.LocalPort != 0 {
@@ -184,17 +183,17 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
 	for _, status := range ps {
 	for _, status := range ps {
 		switch status.Type {
 		switch status.Type {
 		case "tcp":
 		case "tcp":
-			res.Tcp = append(res.Tcp, NewProxyStatusResp(status))
+			res.Tcp = append(res.Tcp, NewProxyStatusResp(status, svr.cfg.ServerAddr))
 		case "udp":
 		case "udp":
-			res.Udp = append(res.Udp, NewProxyStatusResp(status))
+			res.Udp = append(res.Udp, NewProxyStatusResp(status, svr.cfg.ServerAddr))
 		case "http":
 		case "http":
-			res.Http = append(res.Http, NewProxyStatusResp(status))
+			res.Http = append(res.Http, NewProxyStatusResp(status, svr.cfg.ServerAddr))
 		case "https":
 		case "https":
-			res.Https = append(res.Https, NewProxyStatusResp(status))
+			res.Https = append(res.Https, NewProxyStatusResp(status, svr.cfg.ServerAddr))
 		case "stcp":
 		case "stcp":
-			res.Stcp = append(res.Stcp, NewProxyStatusResp(status))
+			res.Stcp = append(res.Stcp, NewProxyStatusResp(status, svr.cfg.ServerAddr))
 		case "xtcp":
 		case "xtcp":
-			res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status))
+			res.Xtcp = append(res.Xtcp, NewProxyStatusResp(status, svr.cfg.ServerAddr))
 		}
 		}
 	}
 	}
 	sort.Sort(ByProxyStatusResp(res.Tcp))
 	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.Code = 400
 		res.Msg = "frpc has no config file path"
 		res.Msg = "frpc has no config file path"
 		log.Warn("%s", res.Msg)
 		log.Warn("%s", res.Msg)
 		return
 		return
 	}
 	}
 
 
-	content, err := config.GetRenderedConfFromFile(g.GlbClientCfg.CfgFile)
+	content, err := config.GetRenderedConfFromFile(svr.cfgFile)
 	if err != nil {
 	if err != nil {
 		res.Code = 400
 		res.Code = 400
 		res.Msg = err.Error()
 		res.Msg = err.Error()
@@ -277,7 +276,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
 
 
 	// get token from origin content
 	// get token from origin content
 	token := ""
 	token := ""
-	b, err := ioutil.ReadFile(g.GlbClientCfg.CfgFile)
+	b, err := ioutil.ReadFile(svr.cfgFile)
 	if err != nil {
 	if err != nil {
 		res.Code = 400
 		res.Code = 400
 		res.Msg = err.Error()
 		res.Msg = err.Error()
@@ -316,7 +315,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	content = strings.Join(newRows, "\n")
 	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 {
 	if err != nil {
 		res.Code = 500
 		res.Code = 500
 		res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
 		res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)

+ 20 - 11
client/control.go

@@ -23,7 +23,6 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/fatedier/frp/client/proxy"
 	"github.com/fatedier/frp/client/proxy"
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/utils/log"
 	"github.com/fatedier/frp/utils/log"
@@ -65,16 +64,24 @@ type Control struct {
 	// last time got the Pong message
 	// last time got the Pong message
 	lastPong time.Time
 	lastPong time.Time
 
 
+	// The client configuration
+	clientCfg config.ClientCommonConf
+
 	readerShutdown     *shutdown.Shutdown
 	readerShutdown     *shutdown.Shutdown
 	writerShutdown     *shutdown.Shutdown
 	writerShutdown     *shutdown.Shutdown
 	msgHandlerShutdown *shutdown.Shutdown
 	msgHandlerShutdown *shutdown.Shutdown
 
 
+	// The UDP port that the server is listening on
+	serverUDPPort int
+
 	mu sync.RWMutex
 	mu sync.RWMutex
 
 
 	log.Logger
 	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{
 	ctl := &Control{
 		runId:              runId,
 		runId:              runId,
 		conn:               conn,
 		conn:               conn,
@@ -84,12 +91,14 @@ func NewControl(runId string, conn frpNet.Conn, session *fmux.Session, pxyCfgs m
 		readCh:             make(chan msg.Message, 100),
 		readCh:             make(chan msg.Message, 100),
 		closedCh:           make(chan struct{}),
 		closedCh:           make(chan struct{}),
 		closedDoneCh:       make(chan struct{}),
 		closedDoneCh:       make(chan struct{}),
+		clientCfg:          clientCfg,
 		readerShutdown:     shutdown.New(),
 		readerShutdown:     shutdown.New(),
 		writerShutdown:     shutdown.New(),
 		writerShutdown:     shutdown.New(),
 		msgHandlerShutdown: shutdown.New(),
 		msgHandlerShutdown: shutdown.New(),
+		serverUDPPort:      serverUDPPort,
 		Logger:             log.NewPrefixLogger(""),
 		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 = NewVisitorManager(ctl)
 	ctl.vm.Reload(visitorCfgs)
 	ctl.vm.Reload(visitorCfgs)
@@ -161,7 +170,7 @@ func (ctl *Control) ClosedDoneCh() <-chan struct{} {
 
 
 // connectServer return a new connection to frps
 // connectServer return a new connection to frps
 func (ctl *Control) connectServer() (conn frpNet.Conn, err error) {
 func (ctl *Control) connectServer() (conn frpNet.Conn, err error) {
-	if g.GlbClientCfg.TcpMux {
+	if ctl.clientCfg.TcpMux {
 		stream, errRet := ctl.session.OpenStream()
 		stream, errRet := ctl.session.OpenStream()
 		if errRet != nil {
 		if errRet != nil {
 			err = errRet
 			err = errRet
@@ -171,13 +180,13 @@ func (ctl *Control) connectServer() (conn frpNet.Conn, err error) {
 		conn = frpNet.WrapConn(stream)
 		conn = frpNet.WrapConn(stream)
 	} else {
 	} else {
 		var tlsConfig *tls.Config
 		var tlsConfig *tls.Config
-		if g.GlbClientCfg.TLSEnable {
+		if ctl.clientCfg.TLSEnable {
 			tlsConfig = &tls.Config{
 			tlsConfig = &tls.Config{
 				InsecureSkipVerify: true,
 				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 {
 		if err != nil {
 			ctl.Warn("start new connection to server error: %v", err)
 			ctl.Warn("start new connection to server error: %v", err)
 			return
 			return
@@ -197,7 +206,7 @@ func (ctl *Control) reader() {
 	defer ctl.readerShutdown.Done()
 	defer ctl.readerShutdown.Done()
 	defer close(ctl.closedCh)
 	defer close(ctl.closedCh)
 
 
-	encReader := crypto.NewReader(ctl.conn, []byte(g.GlbClientCfg.Token))
+	encReader := crypto.NewReader(ctl.conn, []byte(ctl.clientCfg.Token))
 	for {
 	for {
 		if m, err := msg.ReadMsg(encReader); err != nil {
 		if m, err := msg.ReadMsg(encReader); err != nil {
 			if err == io.EOF {
 			if err == io.EOF {
@@ -217,7 +226,7 @@ func (ctl *Control) reader() {
 // writer writes messages got from sendCh to frps
 // writer writes messages got from sendCh to frps
 func (ctl *Control) writer() {
 func (ctl *Control) writer() {
 	defer ctl.writerShutdown.Done()
 	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 {
 	if err != nil {
 		ctl.conn.Error("crypto new writer error: %v", err)
 		ctl.conn.Error("crypto new writer error: %v", err)
 		ctl.conn.Close()
 		ctl.conn.Close()
@@ -246,7 +255,7 @@ func (ctl *Control) msgHandler() {
 	}()
 	}()
 	defer ctl.msgHandlerShutdown.Done()
 	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()
 	defer hbSend.Stop()
 	hbCheck := time.NewTicker(time.Second)
 	hbCheck := time.NewTicker(time.Second)
 	defer hbCheck.Stop()
 	defer hbCheck.Stop()
@@ -260,7 +269,7 @@ func (ctl *Control) msgHandler() {
 			ctl.Debug("send heartbeat to server")
 			ctl.Debug("send heartbeat to server")
 			ctl.sendCh <- &msg.Ping{}
 			ctl.sendCh <- &msg.Ping{}
 		case <-hbCheck.C:
 		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")
 				ctl.Warn("heartbeat timeout")
 				// let reader() stop
 				// let reader() stop
 				ctl.conn.Close()
 				ctl.conn.Close()

+ 13 - 10
client/proxy/proxy.go

@@ -25,7 +25,6 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/models/plugin"
 	"github.com/fatedier/frp/models/plugin"
@@ -51,9 +50,11 @@ type Proxy interface {
 	log.Logger
 	log.Logger
 }
 }
 
 
-func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) {
+func NewProxy(pxyConf config.ProxyConf, clientCfg config.ClientCommonConf, serverUDPPort int) (pxy Proxy) {
 	baseProxy := BaseProxy{
 	baseProxy := BaseProxy{
-		Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName),
+		Logger:        log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName),
+		clientCfg:     clientCfg,
+		serverUDPPort: serverUDPPort,
 	}
 	}
 	switch cfg := pxyConf.(type) {
 	switch cfg := pxyConf.(type) {
 	case *config.TcpProxyConf:
 	case *config.TcpProxyConf:
@@ -91,8 +92,10 @@ func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) {
 }
 }
 
 
 type BaseProxy struct {
 type BaseProxy struct {
-	closed bool
-	mu     sync.RWMutex
+	closed        bool
+	mu            sync.RWMutex
+	clientCfg     config.ClientCommonConf
+	serverUDPPort int
 	log.Logger
 	log.Logger
 }
 }
 
 
@@ -122,7 +125,7 @@ func (pxy *TcpProxy) Close() {
 
 
 func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
-		[]byte(g.GlbClientCfg.Token), m)
+		[]byte(pxy.clientCfg.Token), m)
 }
 }
 
 
 // HTTP
 // HTTP
@@ -151,7 +154,7 @@ func (pxy *HttpProxy) Close() {
 
 
 func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
-		[]byte(g.GlbClientCfg.Token), m)
+		[]byte(pxy.clientCfg.Token), m)
 }
 }
 
 
 // HTTPS
 // HTTPS
@@ -180,7 +183,7 @@ func (pxy *HttpsProxy) Close() {
 
 
 func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
-		[]byte(g.GlbClientCfg.Token), m)
+		[]byte(pxy.clientCfg.Token), m)
 }
 }
 
 
 // STCP
 // STCP
@@ -209,7 +212,7 @@ func (pxy *StcpProxy) Close() {
 
 
 func (pxy *StcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 func (pxy *StcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
 	HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
-		[]byte(g.GlbClientCfg.Token), m)
+		[]byte(pxy.clientCfg.Token), m)
 }
 }
 
 
 // XTCP
 // XTCP
@@ -250,7 +253,7 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn, m *msg.StartWorkConn) {
 		Sid:       natHoleSidMsg.Sid,
 		Sid:       natHoleSidMsg.Sid,
 	}
 	}
 	raddr, _ := net.ResolveUDPAddr("udp",
 	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)
 	clientConn, err := net.DialUDP("udp", nil, raddr)
 	defer clientConn.Close()
 	defer clientConn.Close()
 
 

+ 14 - 7
client/proxy/proxy_manager.go

@@ -20,17 +20,24 @@ type ProxyManager struct {
 	closed bool
 	closed bool
 	mu     sync.RWMutex
 	mu     sync.RWMutex
 
 
+	clientCfg config.ClientCommonConf
+
+	// The UDP port that the server is listening on
+	serverUDPPort int
+
 	logPrefix string
 	logPrefix string
 	log.Logger
 	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{
 	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)
 	addPxyNames := make([]string, 0)
 	for name, cfg := range pxyCfgs {
 	for name, cfg := range pxyCfgs {
 		if _, ok := pm.proxies[name]; !ok {
 		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
 			pm.proxies[name] = pxy
 			addPxyNames = append(addPxyNames, name)
 			addPxyNames = append(addPxyNames, name)
 
 

+ 2 - 2
client/proxy/proxy_wrapper.go

@@ -65,7 +65,7 @@ type ProxyWrapper struct {
 	log.Logger
 	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()
 	baseInfo := cfg.GetBaseInfo()
 	pw := &ProxyWrapper{
 	pw := &ProxyWrapper{
 		ProxyStatus: ProxyStatus{
 		ProxyStatus: ProxyStatus{
@@ -90,7 +90,7 @@ func NewProxyWrapper(cfg config.ProxyConf, eventHandler event.EventHandler, logP
 		pw.Trace("enable health check monitor")
 		pw.Trace("enable health check monitor")
 	}
 	}
 
 
-	pw.pxy = NewProxy(pw.Cfg)
+	pw.pxy = NewProxy(pw.Cfg, clientCfg, serverUDPPort)
 	return pw
 	return pw
 }
 }
 
 

+ 26 - 17
client/service.go

@@ -24,7 +24,6 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/fatedier/frp/assets"
 	"github.com/fatedier/frp/assets"
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/utils/log"
 	"github.com/fatedier/frp/utils/log"
@@ -43,16 +42,26 @@ type Service struct {
 	ctl   *Control
 	ctl   *Control
 	ctlMu sync.RWMutex
 	ctlMu sync.RWMutex
 
 
+	cfg         config.ClientCommonConf
 	pxyCfgs     map[string]config.ProxyConf
 	pxyCfgs     map[string]config.ProxyConf
 	visitorCfgs map[string]config.VisitorConf
 	visitorCfgs map[string]config.VisitorConf
 	cfgMu       sync.RWMutex
 	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
 	exit     uint32 // 0 means not exit
 	closedCh chan int
 	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{
 	svr = &Service{
+		cfg:         cfg,
+		cfgFile:     cfgFile,
 		pxyCfgs:     pxyCfgs,
 		pxyCfgs:     pxyCfgs,
 		visitorCfgs: visitorCfgs,
 		visitorCfgs: visitorCfgs,
 		exit:        0,
 		exit:        0,
@@ -76,14 +85,14 @@ func (svr *Service) Run() error {
 
 
 			// if login_fail_exit is true, just exit this program
 			// if login_fail_exit is true, just exit this program
 			// otherwise sleep a while and try again to connect to server
 			// otherwise sleep a while and try again to connect to server
-			if g.GlbClientCfg.LoginFailExit {
+			if svr.cfg.LoginFailExit {
 				return err
 				return err
 			} else {
 			} else {
 				time.Sleep(10 * time.Second)
 				time.Sleep(10 * time.Second)
 			}
 			}
 		} else {
 		} else {
 			// login success
 			// 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()
 			ctl.Run()
 			svr.ctlMu.Lock()
 			svr.ctlMu.Lock()
 			svr.ctl = ctl
 			svr.ctl = ctl
@@ -94,18 +103,18 @@ func (svr *Service) Run() error {
 
 
 	go svr.keepControllerWorking()
 	go svr.keepControllerWorking()
 
 
-	if g.GlbClientCfg.AdminPort != 0 {
+	if svr.cfg.AdminPort != 0 {
 		// Init admin server assets
 		// Init admin server assets
-		err := assets.Load(g.GlbClientCfg.AssetsDir)
+		err := assets.Load(svr.cfg.AssetsDir)
 		if err != nil {
 		if err != nil {
 			return fmt.Errorf("Load assets error: %v", err)
 			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 {
 		if err != nil {
 			log.Warn("run admin server error: %v", err)
 			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
 	<-svr.closedCh
@@ -137,7 +146,7 @@ func (svr *Service) keepControllerWorking() {
 			// reconnect success, init delayTime
 			// reconnect success, init delayTime
 			delayTime = time.Second
 			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()
 			ctl.Run()
 			svr.ctlMu.Lock()
 			svr.ctlMu.Lock()
 			svr.ctl = ctl
 			svr.ctl = ctl
@@ -152,13 +161,13 @@ func (svr *Service) keepControllerWorking() {
 // session: if it's not nil, using tcp mux
 // session: if it's not nil, using tcp mux
 func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error) {
 func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error) {
 	var tlsConfig *tls.Config
 	var tlsConfig *tls.Config
-	if g.GlbClientCfg.TLSEnable {
+	if svr.cfg.TLSEnable {
 		tlsConfig = &tls.Config{
 		tlsConfig = &tls.Config{
 			InsecureSkipVerify: true,
 			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 {
 	if err != nil {
 		return
 		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 := fmux.DefaultConfig()
 		fmuxCfg.KeepAliveInterval = 20 * time.Second
 		fmuxCfg.KeepAliveInterval = 20 * time.Second
 		fmuxCfg.LogOutput = ioutil.Discard
 		fmuxCfg.LogOutput = ioutil.Discard
@@ -193,10 +202,10 @@ func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error)
 	loginMsg := &msg.Login{
 	loginMsg := &msg.Login{
 		Arch:         runtime.GOARCH,
 		Arch:         runtime.GOARCH,
 		Os:           runtime.GOOS,
 		Os:           runtime.GOOS,
-		PoolCount:    g.GlbClientCfg.PoolCount,
-		User:         g.GlbClientCfg.User,
+		PoolCount:    svr.cfg.PoolCount,
+		User:         svr.cfg.User,
 		Version:      version.Full(),
 		Version:      version.Full(),
-		PrivilegeKey: util.GetAuthKey(g.GlbClientCfg.Token, now),
+		PrivilegeKey: util.GetAuthKey(svr.cfg.Token, now),
 		Timestamp:    now,
 		Timestamp:    now,
 		RunId:        svr.runId,
 		RunId:        svr.runId,
 	}
 	}
@@ -219,7 +228,7 @@ func (svr *Service) login() (conn frpNet.Conn, session *fmux.Session, err error)
 	}
 	}
 
 
 	svr.runId = loginRespMsg.RunId
 	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)
 	log.Info("login to server success, get run id [%s], server udp port [%d]", loginRespMsg.RunId, loginRespMsg.ServerUdpPort)
 	return
 	return
 }
 }

+ 2 - 3
client/visitor.go

@@ -23,7 +23,6 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/models/msg"
 	"github.com/fatedier/frp/utils/log"
 	"github.com/fatedier/frp/utils/log"
@@ -193,13 +192,13 @@ func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) {
 	defer userConn.Close()
 	defer userConn.Close()
 
 
 	sv.Debug("get a new xtcp user connection")
 	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")
 		sv.Error("xtcp is not supported by server")
 		return
 		return
 	}
 	}
 
 
 	raddr, err := net.ResolveUDPAddr("udp",
 	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 {
 	if err != nil {
 		sv.Error("resolve server UDP addr error")
 		sv.Error("resolve server UDP addr error")
 		return
 		return

+ 2 - 2
cmd/frpc/sub/http.go

@@ -54,7 +54,7 @@ var httpCmd = &cobra.Command{
 	Use:   "http",
 	Use:   "http",
 	Short: "Run frpc with a single http proxy",
 	Short: "Run frpc with a single http proxy",
 	RunE: func(cmd *cobra.Command, args []string) error {
 	RunE: func(cmd *cobra.Command, args []string) error {
-		err := parseClientCommonCfg(CfgFileTypeCmd, "")
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
@@ -87,7 +87,7 @@ var httpCmd = &cobra.Command{
 		proxyConfs := map[string]config.ProxyConf{
 		proxyConfs := map[string]config.ProxyConf{
 			cfg.ProxyName: cfg,
 			cfg.ProxyName: cfg,
 		}
 		}
-		err = startService(proxyConfs, nil)
+		err = startService(clientCfg, proxyConfs, nil, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)

+ 2 - 2
cmd/frpc/sub/https.go

@@ -50,7 +50,7 @@ var httpsCmd = &cobra.Command{
 	Use:   "https",
 	Use:   "https",
 	Short: "Run frpc with a single https proxy",
 	Short: "Run frpc with a single https proxy",
 	RunE: func(cmd *cobra.Command, args []string) error {
 	RunE: func(cmd *cobra.Command, args []string) error {
-		err := parseClientCommonCfg(CfgFileTypeCmd, "")
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
@@ -79,7 +79,7 @@ var httpsCmd = &cobra.Command{
 		proxyConfs := map[string]config.ProxyConf{
 		proxyConfs := map[string]config.ProxyConf{
 			cfg.ProxyName: cfg,
 			cfg.ProxyName: cfg,
 		}
 		}
-		err = startService(proxyConfs, nil)
+		err = startService(clientCfg, proxyConfs, nil, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)

+ 7 - 8
cmd/frpc/sub/reload.go

@@ -24,7 +24,6 @@ import (
 
 
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 
 
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 )
 )
 
 
@@ -42,13 +41,13 @@ var reloadCmd = &cobra.Command{
 			os.Exit(1)
 			os.Exit(1)
 		}
 		}
 
 
-		err = parseClientCommonCfg(CfgFileTypeIni, iniContent)
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeIni, iniContent)
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
 		}
 		}
 
 
-		err = reload()
+		err = reload(clientCfg)
 		if err != nil {
 		if err != nil {
 			fmt.Printf("frpc reload error: %v\n", err)
 			fmt.Printf("frpc reload error: %v\n", err)
 			os.Exit(1)
 			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")
 		return fmt.Errorf("admin_port shoud be set if you want to use reload feature")
 	}
 	}
 
 
 	req, err := http.NewRequest("GET", "http://"+
 	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 {
 	if err != nil {
 		return err
 		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)
 	req.Header.Add("Authorization", authStr)
 	resp, err := http.DefaultClient.Do(req)
 	resp, err := http.DefaultClient.Do(req)

+ 35 - 35
cmd/frpc/sub/root.go

@@ -28,7 +28,6 @@ import (
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 
 
 	"github.com/fatedier/frp/client"
 	"github.com/fatedier/frp/client"
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/utils/log"
 	"github.com/fatedier/frp/utils/log"
 	"github.com/fatedier/frp/utils/version"
 	"github.com/fatedier/frp/utils/version"
@@ -114,60 +113,62 @@ func handleSignal(svr *client.Service) {
 	close(kcpDoneCh)
 	close(kcpDoneCh)
 }
 }
 
 
-func parseClientCommonCfg(fileType int, content string) (err error) {
+func parseClientCommonCfg(fileType int, content string) (cfg config.ClientCommonConf, err error) {
 	if fileType == CfgFileTypeIni {
 	if fileType == CfgFileTypeIni {
-		err = parseClientCommonCfgFromIni(content)
+		cfg, err = parseClientCommonCfgFromIni(content)
 	} else if fileType == CfgFileTypeCmd {
 	} else if fileType == CfgFileTypeCmd {
-		err = parseClientCommonCfgFromCmd()
+		cfg, err = parseClientCommonCfgFromCmd()
 	}
 	}
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
 
 
-	err = g.GlbClientCfg.ClientCommonConf.Check()
+	err = cfg.Check()
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
 	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 {
 	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, ":")
 	strs := strings.Split(serverAddr, ":")
 	if len(strs) < 2 {
 	if len(strs) < 2 {
 		err = fmt.Errorf("invalid server_addr")
 		err = fmt.Errorf("invalid server_addr")
 		return
 		return
 	}
 	}
 	if strs[0] != "" {
 	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 {
 	if err != nil {
 		err = fmt.Errorf("invalid server_addr")
 		err = fmt.Errorf("invalid server_addr")
 		return
 		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" {
 	if logFile == "console" {
-		g.GlbClientCfg.LogWay = "console"
+		cfg.LogWay = "console"
 	} else {
 	} else {
-		g.GlbClientCfg.LogWay = "file"
+		cfg.LogWay = "file"
 	}
 	}
-	g.GlbClientCfg.DisableLogColor = disableLogColor
-	return nil
+	cfg.DisableLogColor = disableLogColor
+
+	return
 }
 }
 
 
 func runClient(cfgFilePath string) (err error) {
 func runClient(cfgFilePath string) (err error) {
@@ -176,28 +177,27 @@ func runClient(cfgFilePath string) (err error) {
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
-	g.GlbClientCfg.CfgFile = cfgFilePath
 
 
-	err = parseClientCommonCfg(CfgFileTypeIni, content)
+	cfg, err := parseClientCommonCfg(CfgFileTypeIni, content)
 	if err != nil {
 	if err != nil {
 		return
 		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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	err = startService(pxyCfgs, visitorCfgs)
+	err = startService(cfg, pxyCfgs, visitorCfgs, cfgFilePath)
 	return
 	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, ":") {
 		if !strings.Contains(s, ":") {
 			s += ":53"
 			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 {
 	if errRet != nil {
 		err = errRet
 		err = errRet
 		return
 		return
 	}
 	}
 
 
 	// Capture the exit signal if we use kcp.
 	// Capture the exit signal if we use kcp.
-	if g.GlbClientCfg.Protocol == "kcp" {
+	if cfg.Protocol == "kcp" {
 		go handleSignal(svr)
 		go handleSignal(svr)
 	}
 	}
 
 
 	err = svr.Run()
 	err = svr.Run()
-	if g.GlbClientCfg.Protocol == "kcp" {
+	if cfg.Protocol == "kcp" {
 		<-kcpDoneCh
 		<-kcpDoneCh
 	}
 	}
 	return
 	return

+ 7 - 8
cmd/frpc/sub/status.go

@@ -27,7 +27,6 @@ import (
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 
 
 	"github.com/fatedier/frp/client"
 	"github.com/fatedier/frp/client"
-	"github.com/fatedier/frp/g"
 	"github.com/fatedier/frp/models/config"
 	"github.com/fatedier/frp/models/config"
 )
 )
 
 
@@ -45,13 +44,13 @@ var statusCmd = &cobra.Command{
 			os.Exit(1)
 			os.Exit(1)
 		}
 		}
 
 
-		err = parseClientCommonCfg(CfgFileTypeIni, iniContent)
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeIni, iniContent)
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
 		}
 		}
 
 
-		err = status()
+		err = status(clientCfg)
 		if err != nil {
 		if err != nil {
 			fmt.Printf("frpc get status error: %v\n", err)
 			fmt.Printf("frpc get status error: %v\n", err)
 			os.Exit(1)
 			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")
 		return fmt.Errorf("admin_port shoud be set if you want to get proxy status")
 	}
 	}
 
 
 	req, err := http.NewRequest("GET", "http://"+
 	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 {
 	if err != nil {
 		return err
 		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)
 	req.Header.Add("Authorization", authStr)
 	resp, err := http.DefaultClient.Do(req)
 	resp, err := http.DefaultClient.Do(req)

+ 2 - 2
cmd/frpc/sub/stcp.go

@@ -52,7 +52,7 @@ var stcpCmd = &cobra.Command{
 	Use:   "stcp",
 	Use:   "stcp",
 	Short: "Run frpc with a single stcp proxy",
 	Short: "Run frpc with a single stcp proxy",
 	RunE: func(cmd *cobra.Command, args []string) error {
 	RunE: func(cmd *cobra.Command, args []string) error {
-		err := parseClientCommonCfg(CfgFileTypeCmd, "")
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
@@ -104,7 +104,7 @@ var stcpCmd = &cobra.Command{
 			os.Exit(1)
 			os.Exit(1)
 		}
 		}
 
 
-		err = startService(proxyConfs, visitorConfs)
+		err = startService(clientCfg, proxyConfs, visitorConfs, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)

+ 2 - 2
cmd/frpc/sub/tcp.go

@@ -48,7 +48,7 @@ var tcpCmd = &cobra.Command{
 	Use:   "tcp",
 	Use:   "tcp",
 	Short: "Run frpc with a single tcp proxy",
 	Short: "Run frpc with a single tcp proxy",
 	RunE: func(cmd *cobra.Command, args []string) error {
 	RunE: func(cmd *cobra.Command, args []string) error {
-		err := parseClientCommonCfg(CfgFileTypeCmd, "")
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
@@ -76,7 +76,7 @@ var tcpCmd = &cobra.Command{
 		proxyConfs := map[string]config.ProxyConf{
 		proxyConfs := map[string]config.ProxyConf{
 			cfg.ProxyName: cfg,
 			cfg.ProxyName: cfg,
 		}
 		}
-		err = startService(proxyConfs, nil)
+		err = startService(clientCfg, proxyConfs, nil, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)

+ 2 - 2
cmd/frpc/sub/udp.go

@@ -48,7 +48,7 @@ var udpCmd = &cobra.Command{
 	Use:   "udp",
 	Use:   "udp",
 	Short: "Run frpc with a single udp proxy",
 	Short: "Run frpc with a single udp proxy",
 	RunE: func(cmd *cobra.Command, args []string) error {
 	RunE: func(cmd *cobra.Command, args []string) error {
-		err := parseClientCommonCfg(CfgFileTypeCmd, "")
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
@@ -76,7 +76,7 @@ var udpCmd = &cobra.Command{
 		proxyConfs := map[string]config.ProxyConf{
 		proxyConfs := map[string]config.ProxyConf{
 			cfg.ProxyName: cfg,
 			cfg.ProxyName: cfg,
 		}
 		}
-		err = startService(proxyConfs, nil)
+		err = startService(clientCfg, proxyConfs, nil, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)

+ 2 - 2
cmd/frpc/sub/xtcp.go

@@ -52,7 +52,7 @@ var xtcpCmd = &cobra.Command{
 	Use:   "xtcp",
 	Use:   "xtcp",
 	Short: "Run frpc with a single xtcp proxy",
 	Short: "Run frpc with a single xtcp proxy",
 	RunE: func(cmd *cobra.Command, args []string) error {
 	RunE: func(cmd *cobra.Command, args []string) error {
-		err := parseClientCommonCfg(CfgFileTypeCmd, "")
+		clientCfg, err := parseClientCommonCfg(CfgFileTypeCmd, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)
@@ -104,7 +104,7 @@ var xtcpCmd = &cobra.Command{
 			os.Exit(1)
 			os.Exit(1)
 		}
 		}
 
 
-		err = startService(proxyConfs, visitorConfs)
+		err = startService(clientCfg, proxyConfs, visitorConfs, "")
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			os.Exit(1)
 			os.Exit(1)

+ 0 - 22
g/g.go

@@ -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
-}

+ 5 - 8
models/config/client_common.go

@@ -51,8 +51,8 @@ type ClientCommonConf struct {
 	HeartBeatTimeout  int64               `json:"heartbeat_timeout"`
 	HeartBeatTimeout  int64               `json:"heartbeat_timeout"`
 }
 }
 
 
-func GetDefaultClientConf() *ClientCommonConf {
-	return &ClientCommonConf{
+func GetDefaultClientConf() ClientCommonConf {
+	return ClientCommonConf{
 		ServerAddr:        "0.0.0.0",
 		ServerAddr:        "0.0.0.0",
 		ServerPort:        7000,
 		ServerPort:        7000,
 		HttpProxy:         os.Getenv("http_proxy"),
 		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))
 	conf, err := ini.Load(strings.NewReader(content))
 	if err != nil {
 	if err != nil {
 		err = fmt.Errorf("parse ini conf file error: %v", err)
 		err = fmt.Errorf("parse ini conf file error: %v", err)
-		return nil, err
+		return ClientCommonConf{}, err
 	}
 	}
 
 
 	var (
 	var (