diff --git a/chain.go b/chain.go index de8ad23..306c697 100644 --- a/chain.go +++ b/chain.go @@ -120,6 +120,9 @@ func (c *ProxyChain) Init() { config.Key, _ = c.nodes[0].Users[0].Password() } c.kcpConfig = config + go snmpLogger(config.SnmpLog, config.SnmpPeriod) + go kcpSigHandler() + return } diff --git a/cmd/gost/kcp.json b/cmd/gost/kcp.json index d23550d..00a576a 100644 --- a/cmd/gost/kcp.json +++ b/cmd/gost/kcp.json @@ -15,5 +15,7 @@ "resend": 0, "nc": 0, "sockbuf": 4194304, - "keepalive": 10 + "keepalive": 10, + "snmplog": "", + "snmpperiod": 60 } \ No newline at end of file diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go b/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go index de8ad23..306c697 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go +++ b/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go @@ -120,6 +120,9 @@ func (c *ProxyChain) Init() { config.Key, _ = c.nodes[0].Users[0].Password() } c.kcpConfig = config + go snmpLogger(config.SnmpLog, config.SnmpPeriod) + go kcpSigHandler() + return } diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go b/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go index 10752c3..57085c7 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go +++ b/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go @@ -4,7 +4,9 @@ package gost import ( "crypto/sha1" + "encoding/csv" "encoding/json" + "fmt" "github.com/golang/glog" "github.com/klauspost/compress/snappy" "golang.org/x/crypto/pbkdf2" @@ -12,6 +14,8 @@ import ( "gopkg.in/xtaci/smux.v1" "net" "os" + "os/signal" + "syscall" "time" ) @@ -41,6 +45,8 @@ type KCPConfig struct { NoCongestion int `json:"nc"` SockBuf int `json:"sockbuf"` KeepAlive int `json:"keepalive"` + SnmpLog string `json:"snmplog"` + SnmpPeriod int `json:"snmpperiod"` } func ParseKCPConfig(configFile string) (*KCPConfig, error) { @@ -63,15 +69,15 @@ func ParseKCPConfig(configFile string) (*KCPConfig, error) { func (c *KCPConfig) Init() { switch c.Mode { case "normal": - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 30, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 50, 2, 1 case "fast2": - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 30, 2, 1 case "fast3": - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1 case "fast": fallthrough default: - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 20, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 40, 2, 1 } } @@ -89,11 +95,13 @@ var ( NoComp: false, AckNodelay: false, NoDelay: 0, - Interval: 40, + Interval: 50, Resend: 0, NoCongestion: 0, SockBuf: 4194304, KeepAlive: 10, + SnmpLog: "", + SnmpPeriod: 60, } ) @@ -127,10 +135,12 @@ func (s *KCPServer) ListenAndServe() (err error) { glog.V(LWARNING).Infoln("[kcp]", err) } + go snmpLogger(s.Config.SnmpLog, s.Config.SnmpPeriod) + go kcpSigHandler() for { conn, err := ln.AcceptKCP() if err != nil { - glog.V(LWARNING).Infoln(err) + glog.V(LWARNING).Infoln("[kcp]", err) continue } @@ -209,6 +219,49 @@ func blockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) { return } +func snmpLogger(path string, interval int) { + if path == "" || interval == 0 { + return + } + ticker := time.NewTicker(time.Duration(interval) * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + f, err := os.OpenFile(time.Now().Format(path), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + glog.V(LWARNING).Infoln("[kcp]", err) + return + } + w := csv.NewWriter(f) + // write header in empty file + if stat, err := f.Stat(); err == nil && stat.Size() == 0 { + if err := w.Write(append([]string{"Unix"}, kcp.DefaultSnmp.Header()...)); err != nil { + glog.V(LWARNING).Infoln("[kcp]", err) + } + } + if err := w.Write(append([]string{fmt.Sprint(time.Now().Unix())}, kcp.DefaultSnmp.ToSlice()...)); err != nil { + glog.V(LWARNING).Infoln("[kcp]", err) + } + kcp.DefaultSnmp.Reset() + w.Flush() + f.Close() + } + } +} + +func kcpSigHandler() { + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGUSR1) + + for { + switch <-ch { + case syscall.SIGUSR1: + glog.V(LINFO).Infof("[kcp] SNMP: %+v", kcp.DefaultSnmp.Copy()) + } + } +} + type KCPSession struct { conn net.Conn session *smux.Session diff --git a/cmd/gost/vendor/vendor.json b/cmd/gost/vendor/vendor.json index f7bf836..ceca9ca 100644 --- a/cmd/gost/vendor/vendor.json +++ b/cmd/gost/vendor/vendor.json @@ -21,10 +21,10 @@ "revisionTime": "2017-01-19T05:34:58Z" }, { - "checksumSHA1": "iO+jPih44pGmJmhxHniw6feeIUA=", + "checksumSHA1": "qaLXKRQRMKw/NZ3fVYln3PahmGU=", "path": "github.com/ginuerzh/gost", - "revision": "d5e4e24e8354da5cef62733a4aa8a9d92556945e", - "revisionTime": "2017-02-26T10:31:07Z" + "revision": "82925e4ac7c81687fb985c8cdbf0f072b01c3bc6", + "revisionTime": "2017-03-03T04:48:46Z" }, { "checksumSHA1": "+XIOnTW0rv8Kr/amkXgMraNeUr4=", diff --git a/kcp.go b/kcp.go index 10752c3..57085c7 100644 --- a/kcp.go +++ b/kcp.go @@ -4,7 +4,9 @@ package gost import ( "crypto/sha1" + "encoding/csv" "encoding/json" + "fmt" "github.com/golang/glog" "github.com/klauspost/compress/snappy" "golang.org/x/crypto/pbkdf2" @@ -12,6 +14,8 @@ import ( "gopkg.in/xtaci/smux.v1" "net" "os" + "os/signal" + "syscall" "time" ) @@ -41,6 +45,8 @@ type KCPConfig struct { NoCongestion int `json:"nc"` SockBuf int `json:"sockbuf"` KeepAlive int `json:"keepalive"` + SnmpLog string `json:"snmplog"` + SnmpPeriod int `json:"snmpperiod"` } func ParseKCPConfig(configFile string) (*KCPConfig, error) { @@ -63,15 +69,15 @@ func ParseKCPConfig(configFile string) (*KCPConfig, error) { func (c *KCPConfig) Init() { switch c.Mode { case "normal": - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 30, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 50, 2, 1 case "fast2": - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 30, 2, 1 case "fast3": - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1 case "fast": fallthrough default: - c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 20, 2, 1 + c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 40, 2, 1 } } @@ -89,11 +95,13 @@ var ( NoComp: false, AckNodelay: false, NoDelay: 0, - Interval: 40, + Interval: 50, Resend: 0, NoCongestion: 0, SockBuf: 4194304, KeepAlive: 10, + SnmpLog: "", + SnmpPeriod: 60, } ) @@ -127,10 +135,12 @@ func (s *KCPServer) ListenAndServe() (err error) { glog.V(LWARNING).Infoln("[kcp]", err) } + go snmpLogger(s.Config.SnmpLog, s.Config.SnmpPeriod) + go kcpSigHandler() for { conn, err := ln.AcceptKCP() if err != nil { - glog.V(LWARNING).Infoln(err) + glog.V(LWARNING).Infoln("[kcp]", err) continue } @@ -209,6 +219,49 @@ func blockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) { return } +func snmpLogger(path string, interval int) { + if path == "" || interval == 0 { + return + } + ticker := time.NewTicker(time.Duration(interval) * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + f, err := os.OpenFile(time.Now().Format(path), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + glog.V(LWARNING).Infoln("[kcp]", err) + return + } + w := csv.NewWriter(f) + // write header in empty file + if stat, err := f.Stat(); err == nil && stat.Size() == 0 { + if err := w.Write(append([]string{"Unix"}, kcp.DefaultSnmp.Header()...)); err != nil { + glog.V(LWARNING).Infoln("[kcp]", err) + } + } + if err := w.Write(append([]string{fmt.Sprint(time.Now().Unix())}, kcp.DefaultSnmp.ToSlice()...)); err != nil { + glog.V(LWARNING).Infoln("[kcp]", err) + } + kcp.DefaultSnmp.Reset() + w.Flush() + f.Close() + } + } +} + +func kcpSigHandler() { + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGUSR1) + + for { + switch <-ch { + case syscall.SIGUSR1: + glog.V(LINFO).Infof("[kcp] SNMP: %+v", kcp.DefaultSnmp.Copy()) + } + } +} + type KCPSession struct { conn net.Conn session *smux.Session