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
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 {
@ -139,6 +140,9 @@ func (ctl *Control) HandleNewProxyResp(inMsg *msg.NewProxyResp) {
err := ctl.pm.StartProxy(inMsg.ProxyName, inMsg.RemoteAddr, inMsg.Error)
if err != nil {
ctl.Warn("[%s] start error: %v", inMsg.ProxyName, err)
if ctl.ProxyFunc != nil {
ctl.ProxyFunc(err)
}
} else {
ctl.Info("[%s] start proxy success", inMsg.ProxyName)
}

View File

@ -35,6 +35,10 @@ import (
fmux "github.com/hashicorp/yamux"
)
type ServiceClosedListener interface {
OnClosed(msg string)
}
type Service struct {
// uniq id got from frps, attach it in loginMsg
runId string
@ -51,6 +55,19 @@ type Service struct {
closedCh chan 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) {
@ -67,6 +84,7 @@ func NewService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]conf
exit: 0,
closedCh: make(chan bool),
closed: true,
reConnectCount: 0,
}
return
}
@ -120,6 +138,10 @@ func (svr *Service) Run(cmd bool) error {
go func() {
svr.closed = <-svr.closedCh
log.Info("svr closed")
if svr.onClosedListener != nil {
svr.onClosedListener.OnClosed("")
}
}()
}
return nil
@ -145,6 +167,13 @@ func (svr *Service) keepControllerWorking() {
if delayTime > maxDelayTime {
delayTime = maxDelayTime
}
if svr.ReConnectByCount {
svr.reConnectCount++
if svr.reConnectCount == 3 {
svr.Close()
return
}
}
continue
}
// 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)
}
func NewService(cfgFilePath string) (ser *client.Service, err error) {
cmd = false
crypto.DefaultSalt = "frp"
return returnClient(cfgFilePath, false)
}
func StopFrp() (err error) {
if service == nil {
return fmt.Errorf("frp not start")
@ -214,8 +220,28 @@ func runClient(cfgFilePath string) (err error) {
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
}
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) {
@ -251,3 +277,32 @@ func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]co
}
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
}