frp client

This commit is contained in:
haidy 2019-08-03 21:25:48 +08:00
parent d3f88fe5ea
commit d320d7c030
4 changed files with 152 additions and 8 deletions

View File

@ -71,6 +71,7 @@ type Control struct {
mu sync.RWMutex mu sync.RWMutex
log.Logger log.Logger
ProxyFunc func(err error)
} }
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, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) *Control {
@ -139,6 +140,9 @@ func (ctl *Control) HandleNewProxyResp(inMsg *msg.NewProxyResp) {
err := ctl.pm.StartProxy(inMsg.ProxyName, inMsg.RemoteAddr, inMsg.Error) err := ctl.pm.StartProxy(inMsg.ProxyName, inMsg.RemoteAddr, inMsg.Error)
if err != nil { if err != nil {
ctl.Warn("[%s] start error: %v", inMsg.ProxyName, err) ctl.Warn("[%s] start error: %v", inMsg.ProxyName, err)
if ctl.ProxyFunc != nil {
ctl.ProxyFunc(err)
}
} else { } else {
ctl.Info("[%s] start proxy success", inMsg.ProxyName) ctl.Info("[%s] start proxy success", inMsg.ProxyName)
} }

View File

@ -35,6 +35,10 @@ import (
fmux "github.com/hashicorp/yamux" fmux "github.com/hashicorp/yamux"
) )
type ServiceClosedListener interface {
OnClosed(msg string)
}
type Service struct { type Service struct {
// uniq id got from frps, attach it in loginMsg // uniq id got from frps, attach it in loginMsg
runId string runId string
@ -51,6 +55,19 @@ type Service struct {
closedCh chan bool closedCh chan bool
closed bool closed bool
ReConnectByCount bool
reConnectCount int
onClosedListener ServiceClosedListener
}
func (svr *Service) SetProxyFailedFunc(proxyFailedFunc func(err error)) {
if svr.ctl != nil {
svr.ctl.ProxyFunc = proxyFailedFunc
}
}
func (svr *Service) SetOnCloseListener(listener ServiceClosedListener) {
svr.onClosedListener = listener
} }
func NewService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (svr *Service, err error) { func NewService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (svr *Service, err error) {
@ -67,6 +84,7 @@ func NewService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]conf
exit: 0, exit: 0,
closedCh: make(chan bool), closedCh: make(chan bool),
closed: true, closed: true,
reConnectCount: 0,
} }
return return
} }
@ -120,6 +138,10 @@ func (svr *Service) Run(cmd bool) error {
go func() { go func() {
svr.closed = <-svr.closedCh svr.closed = <-svr.closedCh
log.Info("svr closed") log.Info("svr closed")
if svr.onClosedListener != nil {
svr.onClosedListener.OnClosed("")
}
}() }()
} }
return nil return nil
@ -145,6 +167,13 @@ func (svr *Service) keepControllerWorking() {
if delayTime > maxDelayTime { if delayTime > maxDelayTime {
delayTime = maxDelayTime delayTime = maxDelayTime
} }
if svr.ReConnectByCount {
svr.reConnectCount++
if svr.reConnectCount == 3 {
svr.Close()
return
}
}
continue continue
} }
// reconnect success, init delayTime // reconnect success, init delayTime

56
cmd/frp/frpc.go Normal file
View File

@ -0,0 +1,56 @@
package frp
import (
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/cmd/frpc/sub"
"log"
)
type FRPCService struct {
*client.Service
l FRPCClosedListener
proxyFailedListener ProxyFailedListener
}
type FRPCClosedListener interface {
OnClosed(msg string)
}
type ProxyFailedListener interface {
OnProxyFailed()
}
func (frp *FRPCService) OnClosed(msg string) {
log.Printf("OnClosed() l = %v", frp.l)
if frp.l != nil {
frp.l.OnClosed(msg)
}
}
func (frp *FRPCService) SetFRPCCloseListener(listener FRPCClosedListener) {
frp.l = listener
frp.SetOnCloseListener(frp)
}
func (frp *FRPCService) onProxyFailed(err error) {
if frp.proxyFailedListener != nil {
frp.proxyFailedListener.OnProxyFailed()
}
}
func (frp *FRPCService) SetProxyFailedListener(listener ProxyFailedListener) {
frp.proxyFailedListener = listener
frp.SetProxyFailedFunc(frp.onProxyFailed)
}
func (frp *FRPCService) SetReConnectByCount(reConnectByCount bool) {
frp.ReConnectByCount = reConnectByCount
}
func NewFrpcServiceWithPath(path string) (*FRPCService, error) {
svr, err := sub.NewService(path)
if err != nil {
return nil, err
}
return &FRPCService{Service: svr}, nil
}

View File

@ -117,6 +117,12 @@ func RunFrpc(cfgFilePath string) (err error) {
return runClient(cfgFilePath) return runClient(cfgFilePath)
} }
func NewService(cfgFilePath string) (ser *client.Service, err error) {
cmd = false
crypto.DefaultSalt = "frp"
return returnClient(cfgFilePath, false)
}
func StopFrp() (err error) { func StopFrp() (err error) {
if service == nil { if service == nil {
return fmt.Errorf("frp not start") return fmt.Errorf("frp not start")
@ -214,8 +220,28 @@ func runClient(cfgFilePath string) (err error) {
return err return err
} }
err = startService(pxyCfgs, visitorCfgs) return startService(pxyCfgs, visitorCfgs)
}
func returnClient(cfgFilePath string, run bool) (svr *client.Service, err error) {
var content string
content, err = config.GetRenderedConfFromFile(cfgFilePath)
if err != nil {
return return
}
g.GlbClientCfg.CfgFile = cfgFilePath
err = parseClientCommonCfg(CfgFileTypeIni, content)
if err != nil {
return
}
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(g.GlbClientCfg.User, content, g.GlbClientCfg.Start)
if err != nil {
return nil, err
}
return returnService(pxyCfgs, visitorCfgs)
} }
func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (err error) { func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (err error) {
@ -251,3 +277,32 @@ func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]co
} }
return return
} }
func returnService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) (svr *client.Service, err error) {
log.InitLog(g.GlbClientCfg.LogWay, g.GlbClientCfg.LogFile, g.GlbClientCfg.LogLevel, g.GlbClientCfg.LogMaxDays)
if g.GlbClientCfg.DnsServer != "" {
s := g.GlbClientCfg.DnsServer
if !strings.Contains(s, ":") {
s += ":53"
}
// Change default dns server for frpc
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
return net.Dial("udp", s)
},
}
}
svr, errRet := client.NewService(pxyCfgs, visitorCfgs)
if errRet != nil {
err = errRet
return
}
// Capture the exit signal if we use kcp.
if g.GlbClientCfg.Protocol == "kcp" {
go handleSignal(svr)
}
return svr, err
}