add more log info

This commit is contained in:
fatedier 2017-04-25 00:34:14 +08:00
parent 5360febd72
commit 71f7caa1ee
8 changed files with 122 additions and 47 deletions

View File

@ -144,8 +144,8 @@ func (ctl *Control) NewWorkConn() {
// dispatch this work connection to related proxy // dispatch this work connection to related proxy
if pxy, ok := ctl.proxies[startMsg.ProxyName]; ok { if pxy, ok := ctl.proxies[startMsg.ProxyName]; ok {
go pxy.InWorkConn(workConn)
workConn.Info("start a new work connection") workConn.Info("start a new work connection")
go pxy.InWorkConn(workConn)
} else { } else {
workConn.Close() workConn.Close()
} }
@ -288,7 +288,7 @@ func (ctl *Control) manager() {
} }
cfg, ok := ctl.pxyCfgs[m.ProxyName] cfg, ok := ctl.pxyCfgs[m.ProxyName]
if !ok { if !ok {
// it will never go to this branch // it will never go to this branch now
ctl.Warn("[%s] no proxy conf found", m.ProxyName) ctl.Warn("[%s] no proxy conf found", m.ProxyName)
continue continue
} }
@ -317,12 +317,12 @@ func (ctl *Control) controler() {
maxDelayTime := 30 * time.Second maxDelayTime := 30 * time.Second
delayTime := time.Second delayTime := time.Second
checkInterval := 60 * time.Second checkInterval := 30 * time.Second
checkProxyTicker := time.NewTicker(checkInterval) checkProxyTicker := time.NewTicker(checkInterval)
for { for {
select { select {
case <-checkProxyTicker.C: case <-checkProxyTicker.C:
// Every 60 seconds, check which proxy registered failed and reregister it to server. // Every 30 seconds, check which proxy registered failed and reregister it to server.
for _, cfg := range ctl.pxyCfgs { for _, cfg := range ctl.pxyCfgs {
if _, exist := ctl.proxies[cfg.GetName()]; !exist { if _, exist := ctl.proxies[cfg.GetName()]; !exist {
ctl.Info("try to reregister proxy [%s]", cfg.GetName()) ctl.Info("try to reregister proxy [%s]", cfg.GetName())
@ -337,6 +337,10 @@ func (ctl *Control) controler() {
// close related channels // close related channels
close(ctl.readCh) close(ctl.readCh)
close(ctl.sendCh) close(ctl.sendCh)
for _, pxy := range ctl.proxies {
pxy.Close()
}
time.Sleep(time.Second) time.Sleep(time.Second)
// loop util reconnect to server success // loop util reconnect to server success

View File

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"sync"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
@ -70,6 +71,8 @@ func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy) {
type BaseProxy struct { type BaseProxy struct {
ctl *Control ctl *Control
closed bool
mu sync.RWMutex
log.Logger log.Logger
} }
@ -151,20 +154,34 @@ func (pxy *UdpProxy) Run() (err error) {
} }
func (pxy *UdpProxy) Close() { func (pxy *UdpProxy) Close() {
pxy.mu.Lock()
defer pxy.mu.Unlock()
if !pxy.closed {
pxy.closed = true
if pxy.workConn != nil {
pxy.workConn.Close() pxy.workConn.Close()
}
if pxy.readCh != nil {
close(pxy.readCh) close(pxy.readCh)
}
if pxy.sendCh != nil {
close(pxy.sendCh) close(pxy.sendCh)
}
}
} }
func (pxy *UdpProxy) InWorkConn(conn frpNet.Conn) { func (pxy *UdpProxy) InWorkConn(conn frpNet.Conn) {
if pxy.workConn != nil { pxy.Info("incoming a new work connection for udp proxy")
pxy.workConn.Close() // close resources releated with old workConn
close(pxy.readCh) pxy.Close()
close(pxy.sendCh)
} pxy.mu.Lock()
pxy.workConn = conn pxy.workConn = conn
pxy.readCh = make(chan *msg.UdpPacket, 64) pxy.readCh = make(chan *msg.UdpPacket, 64)
pxy.sendCh = make(chan *msg.UdpPacket, 64) pxy.sendCh = make(chan *msg.UdpPacket, 64)
pxy.closed = false
pxy.mu.Unlock()
workConnReaderFn := func(conn net.Conn) { workConnReaderFn := func(conn net.Conn) {
for { for {
@ -174,9 +191,10 @@ func (pxy *UdpProxy) InWorkConn(conn frpNet.Conn) {
return return
} }
if errRet := errors.PanicToError(func() { if errRet := errors.PanicToError(func() {
pxy.Trace("get udp package from workConn: %s", udpMsg.Content)
pxy.readCh <- &udpMsg pxy.readCh <- &udpMsg
}); errRet != nil { }); errRet != nil {
pxy.Info("reader goroutine for udp work connection closed") pxy.Info("reader goroutine for udp work connection closed: %v", errRet)
return return
} }
} }
@ -184,6 +202,7 @@ func (pxy *UdpProxy) InWorkConn(conn frpNet.Conn) {
workConnSenderFn := func(conn net.Conn) { workConnSenderFn := func(conn net.Conn) {
var errRet error var errRet error
for udpMsg := range pxy.sendCh { for udpMsg := range pxy.sendCh {
pxy.Trace("send udp package to workConn: %s", udpMsg.Content)
if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil { if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil {
pxy.Info("sender goroutine for udp work connection closed") pxy.Info("sender goroutine for udp work connection closed")
return return

View File

@ -11,7 +11,7 @@ server_port = 7000
# console or real logFile path like ./frpc.log # console or real logFile path like ./frpc.log
log_file = ./frpc.log log_file = ./frpc.log
# debug, info, warn, error # trace, debug, info, warn, error
log_level = info log_level = info
log_max_days = 3 log_max_days = 3

View File

@ -21,7 +21,7 @@ dashboard_pwd = admin
# console or real logFile path like ./frps.log # console or real logFile path like ./frps.log
log_file = ./frps.log log_file = ./frps.log
# debug, info, warn, error # trace, debug, info, warn, error
log_level = info log_level = info
log_max_days = 3 log_max_days = 3

View File

@ -51,7 +51,6 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UdpPacket, sendCh
}() }()
// write // write
go func() {
buf := pool.GetBuf(1500) buf := pool.GetBuf(1500)
defer pool.PutBuf(buf) defer pool.PutBuf(buf)
for { for {
@ -60,13 +59,14 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UdpPacket, sendCh
udpConn.Close() udpConn.Close()
return return
} }
// buf[:n] will be encoded to string, so the bytes can be reused
udpMsg := NewUdpPacket(buf[:n], nil, remoteAddr) udpMsg := NewUdpPacket(buf[:n], nil, remoteAddr)
select { select {
case sendCh <- udpMsg: case sendCh <- udpMsg:
default: default:
} }
} }
}() return
} }
func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UdpPacket, sendCh chan<- *msg.UdpPacket) { func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UdpPacket, sendCh chan<- *msg.UdpPacket) {

View File

@ -258,6 +258,7 @@ func (ctl *Control) stoper() {
ctl.writerShutdown.WaitDown() ctl.writerShutdown.WaitDown()
ctl.conn.Close() ctl.conn.Close()
ctl.readerShutdown.WaitDown()
close(ctl.workConnCh) close(ctl.workConnCh)
for workConn := range ctl.workConnCh { for workConn := range ctl.workConnCh {

View File

@ -19,6 +19,7 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"sync"
"time" "time"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
@ -45,6 +46,7 @@ type BaseProxy struct {
name string name string
ctl *Control ctl *Control
listeners []frpNet.Listener listeners []frpNet.Listener
mu sync.RWMutex
log.Logger log.Logger
} }
@ -276,11 +278,23 @@ type UdpProxy struct {
BaseProxy BaseProxy
cfg *config.UdpProxyConf cfg *config.UdpProxyConf
// udpConn is the listener of udp packages
udpConn *net.UDPConn udpConn *net.UDPConn
// there are always only one workConn at the same time
// get another one if it closed
workConn net.Conn workConn net.Conn
// sendCh is used for sending packages to workConn
sendCh chan *msg.UdpPacket sendCh chan *msg.UdpPacket
// readCh is used for reading packages from workConn
readCh chan *msg.UdpPacket readCh chan *msg.UdpPacket
// checkCloseCh is used for watching if workConn is closed
checkCloseCh chan int checkCloseCh chan int
isClosed bool
} }
func (pxy *UdpProxy) Run() (err error) { func (pxy *UdpProxy) Run() (err error) {
@ -300,39 +314,49 @@ func (pxy *UdpProxy) Run() (err error) {
pxy.readCh = make(chan *msg.UdpPacket, 64) pxy.readCh = make(chan *msg.UdpPacket, 64)
pxy.checkCloseCh = make(chan int) pxy.checkCloseCh = make(chan int)
// read message from workConn, if it returns any error, notify proxy to start a new workConn
workConnReaderFn := func(conn net.Conn) { workConnReaderFn := func(conn net.Conn) {
for { for {
var udpMsg msg.UdpPacket var udpMsg msg.UdpPacket
pxy.Trace("loop waiting message from udp workConn")
if errRet := msg.ReadMsgInto(conn, &udpMsg); errRet != nil { if errRet := msg.ReadMsgInto(conn, &udpMsg); errRet != nil {
pxy.Warn("read from workConn for udp error: %v", errRet) pxy.Warn("read from workConn for udp error: %v", errRet)
conn.Close() conn.Close()
// notify proxy to start a new work connection // notify proxy to start a new work connection
// ignore error here, it means the proxy is closed
errors.PanicToError(func() { errors.PanicToError(func() {
pxy.checkCloseCh <- 1 pxy.checkCloseCh <- 1
}) })
return return
} }
if errRet := errors.PanicToError(func() { if errRet := errors.PanicToError(func() {
pxy.Trace("get udp message from workConn: %s", udpMsg.Content)
pxy.readCh <- &udpMsg pxy.readCh <- &udpMsg
StatsAddTrafficOut(pxy.GetName(), int64(len(udpMsg.Content))) StatsAddTrafficOut(pxy.GetName(), int64(len(udpMsg.Content)))
}); errRet != nil { }); errRet != nil {
conn.Close()
pxy.Info("reader goroutine for udp work connection closed") pxy.Info("reader goroutine for udp work connection closed")
return return
} }
} }
} }
// send message to workConn
workConnSenderFn := func(conn net.Conn, ctx context.Context) { workConnSenderFn := func(conn net.Conn, ctx context.Context) {
var errRet error var errRet error
for { for {
select { select {
case udpMsg, ok := <-pxy.sendCh: case udpMsg, ok := <-pxy.sendCh:
if !ok { if !ok {
pxy.Info("sender goroutine for udp work condition closed")
return return
} }
if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil { if errRet = msg.WriteMsg(conn, udpMsg); errRet != nil {
pxy.Info("sender goroutine for udp work connection closed: %v", errRet) pxy.Info("sender goroutine for udp work connection closed: %v", errRet)
conn.Close()
return return
} else { } else {
pxy.Trace("send message to udp workConn: %s", udpMsg.Content)
StatsAddTrafficIn(pxy.GetName(), int64(len(udpMsg.Content))) StatsAddTrafficIn(pxy.GetName(), int64(len(udpMsg.Content)))
continue continue
} }
@ -344,12 +368,12 @@ func (pxy *UdpProxy) Run() (err error) {
} }
go func() { go func() {
for {
// Sleep a while for waiting control send the NewProxyResp to client. // Sleep a while for waiting control send the NewProxyResp to client.
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
for {
workConn, err := pxy.GetWorkConnFromPool() workConn, err := pxy.GetWorkConnFromPool()
if err != nil { if err != nil {
time.Sleep(5 * time.Second) time.Sleep(1 * time.Second)
// check if proxy is closed // check if proxy is closed
select { select {
case _, ok := <-pxy.checkCloseCh: case _, ok := <-pxy.checkCloseCh:
@ -360,6 +384,10 @@ func (pxy *UdpProxy) Run() (err error) {
} }
continue continue
} }
// close the old workConn and replac it with a new one
if pxy.workConn != nil {
pxy.workConn.Close()
}
pxy.workConn = workConn pxy.workConn = workConn
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
go workConnReaderFn(workConn) go workConnReaderFn(workConn)
@ -372,10 +400,14 @@ func (pxy *UdpProxy) Run() (err error) {
} }
}() }()
// Read from user connections and send wrapped udp message to sendCh. // Read from user connections and send wrapped udp message to sendCh (forwarded by workConn).
// Client will transfor udp message to local udp service and waiting for response for a while. // Client will transfor udp message to local udp service and waiting for response for a while.
// Response will be wrapped to be transfored in work connection to server. // Response will be wrapped to be forwarded by work connection to server.
// Close readCh and sendCh at the end.
go func() {
udp.ForwardUserConn(udpConn, pxy.readCh, pxy.sendCh) udp.ForwardUserConn(udpConn, pxy.readCh, pxy.sendCh)
pxy.Close()
}()
return nil return nil
} }
@ -384,12 +416,20 @@ func (pxy *UdpProxy) GetConf() config.ProxyConf {
} }
func (pxy *UdpProxy) Close() { func (pxy *UdpProxy) Close() {
pxy.mu.Lock()
defer pxy.mu.Unlock()
if !pxy.isClosed {
pxy.isClosed = true
pxy.BaseProxy.Close() pxy.BaseProxy.Close()
pxy.workConn.Close() pxy.workConn.Close()
pxy.udpConn.Close() pxy.udpConn.Close()
// all channels only closed here
close(pxy.checkCloseCh) close(pxy.checkCloseCh)
close(pxy.readCh) close(pxy.readCh)
close(pxy.sendCh) close(pxy.sendCh)
}
} }
// HandleUserTcpConnection is used for incoming tcp user connections. // HandleUserTcpConnection is used for incoming tcp user connections.

View File

@ -55,6 +55,8 @@ func SetLogLevel(logLevel string) {
level = 6 level = 6
case "debug": case "debug":
level = 7 level = 7
case "trace":
level = 8
default: default:
level = 4 level = 4
} }
@ -79,6 +81,10 @@ func Debug(format string, v ...interface{}) {
Log.Debug(format, v...) Log.Debug(format, v...)
} }
func Trace(format string, v ...interface{}) {
Log.Trace(format, v...)
}
// Logger // Logger
type Logger interface { type Logger interface {
AddLogPrefix(string) AddLogPrefix(string)
@ -88,6 +94,7 @@ type Logger interface {
Warn(string, ...interface{}) Warn(string, ...interface{})
Info(string, ...interface{}) Info(string, ...interface{})
Debug(string, ...interface{}) Debug(string, ...interface{})
Trace(string, ...interface{})
} }
type PrefixLogger struct { type PrefixLogger struct {
@ -136,3 +143,7 @@ func (pl *PrefixLogger) Info(format string, v ...interface{}) {
func (pl *PrefixLogger) Debug(format string, v ...interface{}) { func (pl *PrefixLogger) Debug(format string, v ...interface{}) {
Log.Debug(pl.prefix+format, v...) Log.Debug(pl.prefix+format, v...)
} }
func (pl *PrefixLogger) Trace(format string, v ...interface{}) {
Log.Trace(pl.prefix+format, v...)
}