Browse Source

frps: optimize code

fatedier 6 years ago
parent
commit
0c7d778896
6 changed files with 116 additions and 109 deletions
  1. 9 9
      server/control.go
  2. 5 5
      server/dashboard.go
  3. 11 11
      server/dashboard_api.go
  4. 6 0
      server/manager.go
  5. 35 35
      server/proxy.go
  6. 50 49
      server/service.go

+ 9 - 9
server/control.go

@@ -35,8 +35,8 @@ import (
 )
 
 type Control struct {
-	// frps service
-	svr *Service
+	// all resource managers and controllers
+	rc *ResourceController
 
 	// login message
 	loginMsg *msg.Login
@@ -81,9 +81,9 @@ type Control struct {
 	mu sync.RWMutex
 }
 
-func NewControl(svr *Service, ctlConn net.Conn, loginMsg *msg.Login) *Control {
+func NewControl(rc *ResourceController, ctlConn net.Conn, loginMsg *msg.Login) *Control {
 	return &Control{
-		svr:             svr,
+		rc:              rc,
 		conn:            ctlConn,
 		loginMsg:        loginMsg,
 		sendCh:          make(chan msg.Message, 10),
@@ -284,11 +284,12 @@ func (ctl *Control) stoper() {
 
 	for _, pxy := range ctl.proxies {
 		pxy.Close()
-		ctl.svr.DelProxy(pxy.GetName())
+		ctl.rc.PxyManager.Del(pxy.GetName())
 		StatsCloseProxy(pxy.GetName(), pxy.GetConf().GetBaseInfo().ProxyType)
 	}
 
 	ctl.allShutdown.Done()
+	ctl.rc.CtlManager.Del(ctl.runId)
 	ctl.conn.Info("client exit success")
 
 	StatsCloseClient()
@@ -358,7 +359,7 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
 
 	// NewProxy will return a interface Proxy.
 	// In fact it create different proxies by different proxy type, we just call run() here.
-	pxy, err := NewProxy(ctl, pxyConf)
+	pxy, err := NewProxy(ctl.runId, ctl.rc, ctl.poolCount, ctl.GetWorkConn, pxyConf)
 	if err != nil {
 		return remoteAddr, err
 	}
@@ -393,7 +394,7 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
 		}
 	}()
 
-	err = ctl.svr.RegisterProxy(pxyMsg.ProxyName, pxy)
+	err = ctl.rc.PxyManager.Add(pxyMsg.ProxyName, pxy)
 	if err != nil {
 		return
 	}
@@ -406,7 +407,6 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
 
 func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
 	ctl.mu.Lock()
-
 	pxy, ok := ctl.proxies[closeMsg.ProxyName]
 	if !ok {
 		ctl.mu.Unlock()
@@ -417,7 +417,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
 		ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
 	}
 	pxy.Close()
-	ctl.svr.DelProxy(pxy.GetName())
+	ctl.rc.PxyManager.Del(pxy.GetName())
 	delete(ctl.proxies, closeMsg.ProxyName)
 	ctl.mu.Unlock()
 

+ 5 - 5
server/dashboard.go

@@ -32,7 +32,7 @@ var (
 	httpServerWriteTimeout = 10 * time.Second
 )
 
-func RunDashboardServer(addr string, port int) (err error) {
+func (svr *Service) RunDashboardServer(addr string, port int) (err error) {
 	// url router
 	router := mux.NewRouter()
 
@@ -40,10 +40,10 @@ func RunDashboardServer(addr string, port int) (err error) {
 	router.Use(frpNet.NewHttpAuthMiddleware(user, passwd).Middleware)
 
 	// api, see dashboard_api.go
-	router.HandleFunc("/api/serverinfo", apiServerInfo).Methods("GET")
-	router.HandleFunc("/api/proxy/{type}", apiProxyByType).Methods("GET")
-	router.HandleFunc("/api/proxy/{type}/{name}", apiProxyByTypeAndName).Methods("GET")
-	router.HandleFunc("/api/traffic/{name}", apiProxyTraffic).Methods("GET")
+	router.HandleFunc("/api/serverinfo", svr.ApiServerInfo).Methods("GET")
+	router.HandleFunc("/api/proxy/{type}", svr.ApiProxyByType).Methods("GET")
+	router.HandleFunc("/api/proxy/{type}/{name}", svr.ApiProxyByTypeAndName).Methods("GET")
+	router.HandleFunc("/api/traffic/{name}", svr.ApiProxyTraffic).Methods("GET")
 
 	// view
 	router.Handle("/favicon.ico", http.FileServer(assets.FileSystem)).Methods("GET")

+ 11 - 11
server/dashboard_api.go

@@ -32,7 +32,6 @@ type GeneralResponse struct {
 	Msg  string `json:"msg"`
 }
 
-// api/serverinfo
 type ServerInfoResp struct {
 	GeneralResponse
 
@@ -55,7 +54,8 @@ type ServerInfoResp struct {
 	ProxyTypeCounts map[string]int64 `json:"proxy_type_count"`
 }
 
-func apiServerInfo(w http.ResponseWriter, r *http.Request) {
+// api/serverinfo
+func (svr *Service) ApiServerInfo(w http.ResponseWriter, r *http.Request) {
 	var (
 		buf []byte
 		res ServerInfoResp
@@ -162,7 +162,7 @@ type GetProxyInfoResp struct {
 }
 
 // api/proxy/:type
-func apiProxyByType(w http.ResponseWriter, r *http.Request) {
+func (svr *Service) ApiProxyByType(w http.ResponseWriter, r *http.Request) {
 	var (
 		buf []byte
 		res GetProxyInfoResp
@@ -177,19 +177,19 @@ func apiProxyByType(w http.ResponseWriter, r *http.Request) {
 	}()
 	log.Info("Http request: [%s]", r.URL.Path)
 
-	res.Proxies = getProxyStatsByType(proxyType)
+	res.Proxies = svr.getProxyStatsByType(proxyType)
 
 	buf, _ = json.Marshal(&res)
 	w.Write(buf)
 
 }
 
-func getProxyStatsByType(proxyType string) (proxyInfos []*ProxyStatsInfo) {
+func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxyStatsInfo) {
 	proxyStats := StatsGetProxiesByType(proxyType)
 	proxyInfos = make([]*ProxyStatsInfo, 0, len(proxyStats))
 	for _, ps := range proxyStats {
 		proxyInfo := &ProxyStatsInfo{}
-		if pxy, ok := ServerService.pxyManager.GetByName(ps.Name); ok {
+		if pxy, ok := svr.rc.PxyManager.GetByName(ps.Name); ok {
 			content, err := json.Marshal(pxy.GetConf())
 			if err != nil {
 				log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
@@ -230,7 +230,7 @@ type GetProxyStatsResp struct {
 }
 
 // api/proxy/:type/:name
-func apiProxyByTypeAndName(w http.ResponseWriter, r *http.Request) {
+func (svr *Service) ApiProxyByTypeAndName(w http.ResponseWriter, r *http.Request) {
 	var (
 		buf []byte
 		res GetProxyStatsResp
@@ -244,20 +244,20 @@ func apiProxyByTypeAndName(w http.ResponseWriter, r *http.Request) {
 	}()
 	log.Info("Http request: [%s]", r.URL.Path)
 
-	res = getProxyStatsByTypeAndName(proxyType, name)
+	res = svr.getProxyStatsByTypeAndName(proxyType, name)
 
 	buf, _ = json.Marshal(&res)
 	w.Write(buf)
 }
 
-func getProxyStatsByTypeAndName(proxyType string, proxyName string) (proxyInfo GetProxyStatsResp) {
+func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName string) (proxyInfo GetProxyStatsResp) {
 	proxyInfo.Name = proxyName
 	ps := StatsGetProxiesByTypeAndName(proxyType, proxyName)
 	if ps == nil {
 		proxyInfo.Code = 1
 		proxyInfo.Msg = "no proxy info found"
 	} else {
-		if pxy, ok := ServerService.pxyManager.GetByName(proxyName); ok {
+		if pxy, ok := svr.rc.PxyManager.GetByName(proxyName); ok {
 			content, err := json.Marshal(pxy.GetConf())
 			if err != nil {
 				log.Warn("marshal proxy [%s] conf info error: %v", ps.Name, err)
@@ -295,7 +295,7 @@ type GetProxyTrafficResp struct {
 	TrafficOut []int64 `json:"traffic_out"`
 }
 
-func apiProxyTraffic(w http.ResponseWriter, r *http.Request) {
+func (svr *Service) ApiProxyTraffic(w http.ResponseWriter, r *http.Request) {
 	var (
 		buf []byte
 		res GetProxyTrafficResp

+ 6 - 0
server/manager.go

@@ -50,6 +50,12 @@ func (cm *ControlManager) Add(runId string, ctl *Control) (oldCtl *Control) {
 	return
 }
 
+func (cm *ControlManager) Del(runId string) {
+	cm.mu.Lock()
+	defer cm.mu.Unlock()
+	delete(cm.ctlsByRunId, runId)
+}
+
 func (cm *ControlManager) GetById(runId string) (ctl *Control, ok bool) {
 	cm.mu.RLock()
 	defer cm.mu.RUnlock()

+ 35 - 35
server/proxy.go

@@ -36,9 +36,10 @@ import (
 	frpIo "github.com/fatedier/golib/io"
 )
 
+type GetWorkConnFn func() (frpNet.Conn, error)
+
 type Proxy interface {
 	Run() (remoteAddr string, err error)
-	GetControl() *Control
 	GetName() string
 	GetConf() config.ProxyConf
 	GetWorkConnFromPool() (workConn frpNet.Conn, err error)
@@ -48,10 +49,12 @@ type Proxy interface {
 }
 
 type BaseProxy struct {
-	name         string
-	ctl          *Control
-	listeners    []frpNet.Listener
-	usedPortsNum int
+	name          string
+	rc            *ResourceController
+	listeners     []frpNet.Listener
+	usedPortsNum  int
+	poolCount     int
+	getWorkConnFn GetWorkConnFn
 
 	mu sync.RWMutex
 	log.Logger
@@ -61,10 +64,6 @@ func (pxy *BaseProxy) GetName() string {
 	return pxy.name
 }
 
-func (pxy *BaseProxy) GetControl() *Control {
-	return pxy.ctl
-}
-
 func (pxy *BaseProxy) GetUsedPortsNum() int {
 	return pxy.usedPortsNum
 }
@@ -77,10 +76,9 @@ func (pxy *BaseProxy) Close() {
 }
 
 func (pxy *BaseProxy) GetWorkConnFromPool() (workConn frpNet.Conn, err error) {
-	ctl := pxy.GetControl()
 	// try all connections from the pool
-	for i := 0; i < ctl.poolCount+1; i++ {
-		if workConn, err = ctl.GetWorkConn(); err != nil {
+	for i := 0; i < pxy.poolCount+1; i++ {
+		if workConn, err = pxy.getWorkConnFn(); err != nil {
 			pxy.Warn("failed to get work connection: %v", err)
 			return
 		}
@@ -126,12 +124,14 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, frpNet.Con
 	}
 }
 
-func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy, err error) {
+func NewProxy(runId string, rc *ResourceController, poolCount int, getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf) (pxy Proxy, err error) {
 	basePxy := BaseProxy{
-		name:      pxyConf.GetBaseInfo().ProxyName,
-		ctl:       ctl,
-		listeners: make([]frpNet.Listener, 0),
-		Logger:    log.NewPrefixLogger(ctl.runId),
+		name:          pxyConf.GetBaseInfo().ProxyName,
+		rc:            rc,
+		listeners:     make([]frpNet.Listener, 0),
+		poolCount:     poolCount,
+		getWorkConnFn: getWorkConnFn,
+		Logger:        log.NewPrefixLogger(runId),
 	}
 	switch cfg := pxyConf.(type) {
 	case *config.TcpProxyConf:
@@ -182,7 +182,7 @@ type TcpProxy struct {
 
 func (pxy *TcpProxy) Run() (remoteAddr string, err error) {
 	if pxy.cfg.Group != "" {
-		l, realPort, errRet := pxy.ctl.svr.tcpGroupCtl.Listen(pxy.name, pxy.cfg.Group, pxy.cfg.GroupKey, g.GlbServerCfg.ProxyBindAddr, pxy.cfg.RemotePort)
+		l, realPort, errRet := pxy.rc.TcpGroupCtl.Listen(pxy.name, pxy.cfg.Group, pxy.cfg.GroupKey, g.GlbServerCfg.ProxyBindAddr, pxy.cfg.RemotePort)
 		if errRet != nil {
 			err = errRet
 			return
@@ -198,13 +198,13 @@ func (pxy *TcpProxy) Run() (remoteAddr string, err error) {
 		pxy.listeners = append(pxy.listeners, listener)
 		pxy.Info("tcp proxy listen port [%d] in group [%s]", pxy.cfg.RemotePort, pxy.cfg.Group)
 	} else {
-		pxy.realPort, err = pxy.ctl.svr.tcpPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)
+		pxy.realPort, err = pxy.rc.TcpPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)
 		if err != nil {
 			return
 		}
 		defer func() {
 			if err != nil {
-				pxy.ctl.svr.tcpPortManager.Release(pxy.realPort)
+				pxy.rc.TcpPortManager.Release(pxy.realPort)
 			}
 		}()
 		listener, errRet := frpNet.ListenTcp(g.GlbServerCfg.ProxyBindAddr, pxy.realPort)
@@ -230,7 +230,7 @@ func (pxy *TcpProxy) GetConf() config.ProxyConf {
 func (pxy *TcpProxy) Close() {
 	pxy.BaseProxy.Close()
 	if pxy.cfg.Group == "" {
-		pxy.ctl.svr.tcpPortManager.Release(pxy.realPort)
+		pxy.rc.TcpPortManager.Release(pxy.realPort)
 	}
 }
 
@@ -260,7 +260,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
 		routeConfig.Domain = domain
 		for _, location := range locations {
 			routeConfig.Location = location
-			err = pxy.ctl.svr.httpReverseProxy.Register(routeConfig)
+			err = pxy.rc.HttpReverseProxy.Register(routeConfig)
 			if err != nil {
 				return
 			}
@@ -268,7 +268,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
 			tmpLocation := routeConfig.Location
 			addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(g.GlbServerCfg.VhostHttpPort)))
 			pxy.closeFuncs = append(pxy.closeFuncs, func() {
-				pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation)
+				pxy.rc.HttpReverseProxy.UnRegister(tmpDomain, tmpLocation)
 			})
 			pxy.Info("http proxy listen for host [%s] location [%s]", routeConfig.Domain, routeConfig.Location)
 		}
@@ -278,7 +278,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
 		routeConfig.Domain = pxy.cfg.SubDomain + "." + g.GlbServerCfg.SubDomainHost
 		for _, location := range locations {
 			routeConfig.Location = location
-			err = pxy.ctl.svr.httpReverseProxy.Register(routeConfig)
+			err = pxy.rc.HttpReverseProxy.Register(routeConfig)
 			if err != nil {
 				return
 			}
@@ -286,7 +286,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
 			tmpLocation := routeConfig.Location
 			addrs = append(addrs, util.CanonicalAddr(tmpDomain, g.GlbServerCfg.VhostHttpPort))
 			pxy.closeFuncs = append(pxy.closeFuncs, func() {
-				pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation)
+				pxy.rc.HttpReverseProxy.UnRegister(tmpDomain, tmpLocation)
 			})
 			pxy.Info("http proxy listen for host [%s] location [%s]", routeConfig.Domain, routeConfig.Location)
 		}
@@ -348,7 +348,7 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) {
 	addrs := make([]string, 0)
 	for _, domain := range pxy.cfg.CustomDomains {
 		routeConfig.Domain = domain
-		l, errRet := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig)
+		l, errRet := pxy.rc.VhostHttpsMuxer.Listen(routeConfig)
 		if errRet != nil {
 			err = errRet
 			return
@@ -361,7 +361,7 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) {
 
 	if pxy.cfg.SubDomain != "" {
 		routeConfig.Domain = pxy.cfg.SubDomain + "." + g.GlbServerCfg.SubDomainHost
-		l, errRet := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig)
+		l, errRet := pxy.rc.VhostHttpsMuxer.Listen(routeConfig)
 		if errRet != nil {
 			err = errRet
 			return
@@ -391,7 +391,7 @@ type StcpProxy struct {
 }
 
 func (pxy *StcpProxy) Run() (remoteAddr string, err error) {
-	listener, errRet := pxy.ctl.svr.visitorManager.Listen(pxy.GetName(), pxy.cfg.Sk)
+	listener, errRet := pxy.rc.VisitorManager.Listen(pxy.GetName(), pxy.cfg.Sk)
 	if errRet != nil {
 		err = errRet
 		return
@@ -410,7 +410,7 @@ func (pxy *StcpProxy) GetConf() config.ProxyConf {
 
 func (pxy *StcpProxy) Close() {
 	pxy.BaseProxy.Close()
-	pxy.ctl.svr.visitorManager.CloseListener(pxy.GetName())
+	pxy.rc.VisitorManager.CloseListener(pxy.GetName())
 }
 
 type XtcpProxy struct {
@@ -421,12 +421,12 @@ type XtcpProxy struct {
 }
 
 func (pxy *XtcpProxy) Run() (remoteAddr string, err error) {
-	if pxy.ctl.svr.natHoleController == nil {
+	if pxy.rc.NatHoleController == nil {
 		pxy.Error("udp port for xtcp is not specified.")
 		err = fmt.Errorf("xtcp is not supported in frps")
 		return
 	}
-	sidCh := pxy.ctl.svr.natHoleController.ListenClient(pxy.GetName(), pxy.cfg.Sk)
+	sidCh := pxy.rc.NatHoleController.ListenClient(pxy.GetName(), pxy.cfg.Sk)
 	go func() {
 		for {
 			select {
@@ -456,7 +456,7 @@ func (pxy *XtcpProxy) GetConf() config.ProxyConf {
 
 func (pxy *XtcpProxy) Close() {
 	pxy.BaseProxy.Close()
-	pxy.ctl.svr.natHoleController.CloseClient(pxy.GetName())
+	pxy.rc.NatHoleController.CloseClient(pxy.GetName())
 	errors.PanicToError(func() {
 		close(pxy.closeCh)
 	})
@@ -488,13 +488,13 @@ type UdpProxy struct {
 }
 
 func (pxy *UdpProxy) Run() (remoteAddr string, err error) {
-	pxy.realPort, err = pxy.ctl.svr.udpPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)
+	pxy.realPort, err = pxy.rc.UdpPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)
 	if err != nil {
 		return
 	}
 	defer func() {
 		if err != nil {
-			pxy.ctl.svr.udpPortManager.Release(pxy.realPort)
+			pxy.rc.UdpPortManager.Release(pxy.realPort)
 		}
 	}()
 
@@ -648,7 +648,7 @@ func (pxy *UdpProxy) Close() {
 		close(pxy.readCh)
 		close(pxy.sendCh)
 	}
-	pxy.ctl.svr.udpPortManager.Release(pxy.realPort)
+	pxy.rc.UdpPortManager.Release(pxy.realPort)
 }
 
 // HandleUserTcpConnection is used for incoming tcp user connections.

+ 50 - 49
server/service.go

@@ -43,6 +43,36 @@ const (
 
 var ServerService *Service
 
+// All resource managers and controllers
+type ResourceController struct {
+	// Manage all controllers
+	CtlManager *ControlManager
+
+	// Manage all proxies
+	PxyManager *ProxyManager
+
+	// Manage all visitor listeners
+	VisitorManager *VisitorManager
+
+	// Tcp Group Controller
+	TcpGroupCtl *group.TcpGroupCtl
+
+	// Manage all tcp ports
+	TcpPortManager *ports.PortManager
+
+	// Manage all udp ports
+	UdpPortManager *ports.PortManager
+
+	// For http proxies, forwarding http requests
+	HttpReverseProxy *vhost.HttpReverseProxy
+
+	// For https proxies, route requests to different clients by hostname and other infomation
+	VhostHttpsMuxer *vhost.HttpsMuxer
+
+	// Controller for nat hole connections
+	NatHoleController *NatHoleController
+}
+
 // Server service
 type Service struct {
 	// Dispatch connections to different handlers listen on same port
@@ -57,43 +87,22 @@ type Service struct {
 	// Accept connections using websocket
 	websocketListener frpNet.Listener
 
-	// For https proxies, route requests to different clients by hostname and other infomation
-	VhostHttpsMuxer *vhost.HttpsMuxer
-
-	httpReverseProxy *vhost.HttpReverseProxy
-
-	// Manage all controllers
-	ctlManager *ControlManager
-
-	// Manage all proxies
-	pxyManager *ProxyManager
-
-	// Manage all visitor listeners
-	visitorManager *VisitorManager
-
-	// Manage all tcp ports
-	tcpPortManager *ports.PortManager
-
-	// Manage all udp ports
-	udpPortManager *ports.PortManager
-
-	// Tcp Group Controller
-	tcpGroupCtl *group.TcpGroupCtl
-
-	// Controller for nat hole connections
-	natHoleController *NatHoleController
+	// All resource managers and controllers
+	rc *ResourceController
 }
 
 func NewService() (svr *Service, err error) {
 	cfg := &g.GlbServerCfg.ServerCommonConf
 	svr = &Service{
-		ctlManager:     NewControlManager(),
-		pxyManager:     NewProxyManager(),
-		visitorManager: NewVisitorManager(),
-		tcpPortManager: ports.NewPortManager("tcp", cfg.ProxyBindAddr, cfg.AllowPorts),
-		udpPortManager: ports.NewPortManager("udp", cfg.ProxyBindAddr, cfg.AllowPorts),
+		rc: &ResourceController{
+			CtlManager:     NewControlManager(),
+			PxyManager:     NewProxyManager(),
+			VisitorManager: NewVisitorManager(),
+			TcpPortManager: ports.NewPortManager("tcp", cfg.ProxyBindAddr, cfg.AllowPorts),
+			UdpPortManager: ports.NewPortManager("udp", cfg.ProxyBindAddr, cfg.AllowPorts),
+		},
 	}
-	svr.tcpGroupCtl = group.NewTcpGroupCtl(svr.tcpPortManager)
+	svr.rc.TcpGroupCtl = group.NewTcpGroupCtl(svr.rc.TcpPortManager)
 
 	// Init assets.
 	err = assets.Load(cfg.AssetsDir)
@@ -151,7 +160,7 @@ func NewService() (svr *Service, err error) {
 		rp := vhost.NewHttpReverseProxy(vhost.HttpReverseProxyOptions{
 			ResponseHeaderTimeoutS: cfg.VhostHttpTimeout,
 		})
-		svr.httpReverseProxy = rp
+		svr.rc.HttpReverseProxy = rp
 
 		address := fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpPort)
 		server := &http.Server{
@@ -185,7 +194,7 @@ func NewService() (svr *Service, err error) {
 			}
 		}
 
-		svr.VhostHttpsMuxer, err = vhost.NewHttpsMuxer(frpNet.WrapLogListener(l), 30*time.Second)
+		svr.rc.VhostHttpsMuxer, err = vhost.NewHttpsMuxer(frpNet.WrapLogListener(l), 30*time.Second)
 		if err != nil {
 			err = fmt.Errorf("Create vhost httpsMuxer error, %v", err)
 			return
@@ -202,13 +211,13 @@ func NewService() (svr *Service, err error) {
 			err = fmt.Errorf("Create nat hole controller error, %v", err)
 			return
 		}
-		svr.natHoleController = nc
+		svr.rc.NatHoleController = nc
 		log.Info("nat hole udp service listen on %s:%d", cfg.BindAddr, cfg.BindUdpPort)
 	}
 
 	// Create dashboard web server.
 	if cfg.DashboardPort > 0 {
-		err = RunDashboardServer(cfg.DashboardAddr, cfg.DashboardPort)
+		err = svr.RunDashboardServer(cfg.DashboardAddr, cfg.DashboardPort)
 		if err != nil {
 			err = fmt.Errorf("Create dashboard web server error, %v", err)
 			return
@@ -220,8 +229,8 @@ func NewService() (svr *Service, err error) {
 }
 
 func (svr *Service) Run() {
-	if svr.natHoleController != nil {
-		go svr.natHoleController.Run()
+	if svr.rc.NatHoleController != nil {
+		go svr.rc.NatHoleController.Run()
 	}
 	if g.GlbServerCfg.KcpBindPort > 0 {
 		go svr.HandleListener(svr.kcpListener)
@@ -346,9 +355,9 @@ func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (e
 		}
 	}
 
-	ctl := NewControl(svr, ctlConn, loginMsg)
+	ctl := NewControl(svr.rc, ctlConn, loginMsg)
 
-	if oldCtl := svr.ctlManager.Add(loginMsg.RunId, ctl); oldCtl != nil {
+	if oldCtl := svr.rc.CtlManager.Add(loginMsg.RunId, ctl); oldCtl != nil {
 		oldCtl.allShutdown.WaitDone()
 	}
 
@@ -362,7 +371,7 @@ func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (e
 
 // RegisterWorkConn register a new work connection to control and proxies need it.
 func (svr *Service) RegisterWorkConn(workConn frpNet.Conn, newMsg *msg.NewWorkConn) {
-	ctl, exist := svr.ctlManager.GetById(newMsg.RunId)
+	ctl, exist := svr.rc.CtlManager.GetById(newMsg.RunId)
 	if !exist {
 		workConn.Warn("No client control found for run id [%s]", newMsg.RunId)
 		return
@@ -372,14 +381,6 @@ func (svr *Service) RegisterWorkConn(workConn frpNet.Conn, newMsg *msg.NewWorkCo
 }
 
 func (svr *Service) RegisterVisitorConn(visitorConn frpNet.Conn, newMsg *msg.NewVisitorConn) error {
-	return svr.visitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
+	return svr.rc.VisitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
 		newMsg.UseEncryption, newMsg.UseCompression)
 }
-
-func (svr *Service) RegisterProxy(name string, pxy Proxy) error {
-	return svr.pxyManager.Add(name, pxy)
-}
-
-func (svr *Service) DelProxy(name string) {
-	svr.pxyManager.Del(name)
-}