diff --git a/.gitignore b/.gitignore index 8690dea..893e012 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ server.exe vnet vnet.exe config.json -*.test.exe \ No newline at end of file +*.test.exe +*.pprof \ No newline at end of file diff --git a/cmd/test/test.go b/cmd/test/test.go index bfa72b1..0a35f9a 100644 --- a/cmd/test/test.go +++ b/cmd/test/test.go @@ -2,20 +2,25 @@ package main import ( "fmt" - "os" - "os/signal" - "syscall" + "time" ) func main() { - c := make(chan os.Signal) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - for { - data := <-c - fmt.Println(data.String()) - if data == os.Interrupt { - return - } - } - + go func() { + defer func() { + if e := recover(); e != nil { + fmt.Printf("error %v", e) + } + }() + go func() { + defer func() { + if e := recover(); e != nil { + fmt.Printf("error %v \n", e) + } + }() + panic("this is error") + }() + }() + time.Sleep(1 * time.Second) + fmt.Println("aaa") } diff --git a/cmd/test/test_test.go b/cmd/test/test_test.go new file mode 100644 index 0000000..452d7a3 --- /dev/null +++ b/cmd/test/test_test.go @@ -0,0 +1,17 @@ +package main + +import "testing" + +func Benchmark_panic(t *testing.B) { + t.ResetTimer() + for i := 0; i < t.N; i++ { + func() { + defer func() { + if e := recover(); e != nil { + + } + }() + panic(100) + }() + } +} diff --git a/common/auth/auth.go b/common/auth/auth.go new file mode 100644 index 0000000..c3b152f --- /dev/null +++ b/common/auth/auth.go @@ -0,0 +1,3 @@ +package auth + +// TODO socks5 auth diff --git a/common/ciphers/ssstream/cipher_packet.go b/common/ciphers/ssstream/cipher_packet.go index ac84ded..d841fbd 100644 --- a/common/ciphers/ssstream/cipher_packet.go +++ b/common/ciphers/ssstream/cipher_packet.go @@ -2,11 +2,12 @@ package ssstream import ( "crypto/rand" - "errors" + "fmt" "io" "net" "sync" + "github.com/pkg/errors" "github.com/rc452860/vnet/common/pool" ) @@ -42,7 +43,7 @@ func GetStreamPacketCiphers(method string) func(string, net.PacketConn) (net.Pac } } -func (c *streamPacket) WriteTo(b []byte, addr net.Addr) (int, error) { +func (c *streamPacket) WriteTo(b []byte, addr net.Addr) (n int, err error) { c.Lock() defer c.Unlock() ivLen := c.IVLen() @@ -63,8 +64,13 @@ func (c *streamPacket) WriteTo(b []byte, addr net.Addr) (int, error) { return dataLen, nil } -func (c *streamPacket) ReadFrom(b []byte) (int, net.Addr, error) { - n, addr, err := c.PacketConn.ReadFrom(b) +func (c *streamPacket) ReadFrom(b []byte) (n int, addr net.Addr, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.WithStack(errors.New(fmt.Sprintf("%v", e))) + } + }() + n, addr, err = c.PacketConn.ReadFrom(b) if err != nil { return n, addr, err diff --git a/common/config/config.go b/common/config/config.go index f794aa6..b874882 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -8,6 +8,7 @@ import ( "github.com/rc452860/vnet/common/log" "github.com/rc452860/vnet/utils" + "github.com/rc452860/vnet/utils/iox" ) var ( @@ -40,6 +41,7 @@ type DbConfig struct { NodeId int `json:"node_id` SyncTime int `json:"sync_time"` OnlineSyncTime int `json:"online_sync_time"` + Level int `json:"level"` } // ShadowsocksOptions is global shadowoscks service config @@ -56,7 +58,8 @@ func DefaultConfig() *Config { return &Config{ Mode: "db", DbConfig: DbConfig{ - Rate: -1, + Level: -1, + Rate: -1, }, ShadowsocksOptions: ShadowsocksOptions{ ConnectTimeout: 3000, @@ -89,7 +92,7 @@ func LoadDefault() (*Config, error) { func LoadConfig(file string) (*Config, error) { utils.RLock(file) defer utils.RUnLock(file) - if !utils.IsFileExist(file) { + if !iox.IsFileExist(file) { absFile, err := filepath.Abs(file) if err != nil { log.Err(err) diff --git a/common/pool/pool.go b/common/pool/pool.go index 8341eae..e9c2b81 100644 --- a/common/pool/pool.go +++ b/common/pool/pool.go @@ -4,24 +4,46 @@ import "sync" const BufferSize = 4108 +var ( + poolMap map[int]*sync.Pool +) + func init() { - pool = &sync.Pool{ - New: func() interface{} { - return make([]byte, BufferSize) - }, - } + poolMap = make(map[int]*sync.Pool) } -var pool *sync.Pool - func GetBuf() []byte { - buf := pool.Get().([]byte) + pool := poolMap[BufferSize] + if pool == nil { + poolMap[BufferSize] = &sync.Pool{ + New: createAllocFunc(BufferSize), + } + } + buf := poolMap[BufferSize].Get().([]byte) + buf = buf[:cap(buf)] + return buf +} + +func GetBufBySize(size int) []byte { + pool := poolMap[size] + if pool == nil { + poolMap[size] = &sync.Pool{ + New: createAllocFunc(size), + } + } + buf := poolMap[size].Get().([]byte) buf = buf[:cap(buf)] return buf } func PutBuf(buf []byte) { - pool.Put(buf) + poolMap[cap(buf)].Put(buf) +} + +func createAllocFunc(size int) func() interface{} { + return func() interface{} { + return make([]byte, size) + } } // type BytesPool struct { diff --git a/db/db.go b/db/db.go index ffb4249..6036d42 100644 --- a/db/db.go +++ b/db/db.go @@ -103,6 +103,18 @@ func GetEnableUser() ([]User, error) { return userList, nil } +func GetUserWithLevel(level int) ([]User, error) { + connect, err := Connect() + if err != nil { + return nil, err + } + defer connect.Close() + + var userList []User + connect.Where("port != 0 AND enable = 1 AND level = level").Find(&userList) + return userList, nil +} + func DbStarted(ctx context.Context) { conf := config.CurrentConfig() if conf.DbConfig.Host == "" { @@ -238,7 +250,15 @@ func DBServiceMonitor(ctx context.Context) { return default: } - users, err := GetEnableUser() + var ( + users []User + err error + ) + if conf.Level != -1 { + users, err = GetEnableUser() + } else { + users, err = GetUserWithLevel(conf.Level) + } if err != nil { log.Err(err) continue diff --git a/proxy/server/shadowsocks.go b/proxy/server/shadowsocks.go index 9ff8315..8fcfe58 100644 --- a/proxy/server/shadowsocks.go +++ b/proxy/server/shadowsocks.go @@ -10,6 +10,7 @@ import ( "time" "github.com/rc452860/vnet/component/dnsx" + "github.com/rc452860/vnet/utils/addr" "github.com/pkg/errors" @@ -157,8 +158,8 @@ func (s *ShadowsocksProxy) tcpDownload(con conn.IConn, down uint64) { // start shadowsocks tcp proxy service func (s *ShadowsocksProxy) startTCP() error { - addr := fmt.Sprintf("%s:%d", s.Host, s.Port) - tcpAddr, err := net.ResolveTCPAddr("tcp", addr) + serverAddr := fmt.Sprintf("%s:%d", s.Host, s.Port) + tcpAddr, err := net.ResolveTCPAddr("tcp", serverAddr) if err != nil { logging.Error(err.Error()) return err @@ -220,15 +221,15 @@ func (s *ShadowsocksProxy) startTCP() error { /** 读取目标地址 */ targetAddr, err := socks.ReadAddr(lcd) if err != nil { - log.Error("read target address error %s. (maybe the crypto method wrong configuration)", err.Error()) + log.Error("tcp:%v read target address error %s. (maybe the crypto method wrong configuration)", addr.GetPortFromAddr(server.Addr()), err.Error()) return } - addr, err := s.dnsReslove(targetAddr) + resloveAddr, err := s.dnsReslove(targetAddr) if err != nil { log.Err(err) return } - rc, err := net.Dial("tcp", addr) + rc, err := net.Dial("tcp", resloveAddr) if err != nil { logging.Error("connect target:%s error cause: %v", targetAddr, err) return @@ -238,7 +239,6 @@ func (s *ShadowsocksProxy) startTCP() error { s.ConnectionStage(s.TCP.Addr(), lcd.RemoteAddr(), rc.RemoteAddr(), targetAddr) rc.(*net.TCPConn).SetKeepAlive(true) - // logging.Info("tcp %s <----> %s", lcd.RemoteAddr(), targetAddr) /** 默认装饰器 */ rcd, err := conn.DefaultDecorate(rc, conn.TCP) @@ -316,8 +316,8 @@ func (s *ShadowsocksProxy) udpDownload(laddr, raddr net.Addr, n uint64) { // Listen on addr for encrypted packets and basically do UDP NAT. func (s *ShadowsocksProxy) startUDP() error { - addr := fmt.Sprintf("%s:%d", s.Host, s.Port) - server, err := net.ListenPacket("udp", addr) + serverAddr := fmt.Sprintf("%s:%d", s.Host, s.Port) + server, err := net.ListenPacket("udp", serverAddr) if err != nil { logging.Error("UDP remote listen error: %v", err) return errors.Cause(err) @@ -359,7 +359,7 @@ func (s *ShadowsocksProxy) startUDP() error { } tgtAddr := socks.SplitAddr(buf[:n]) if tgtAddr == nil { - logging.Error("failed to split target address from packet: %q", buf[:n]) + logging.Error("udp:%v read target address error. (maybe the crypto method wrong configuration)", addr.GetPortFromAddr(server.LocalAddr())) continue } addr, err := s.dnsReslove(tgtAddr) @@ -367,7 +367,6 @@ func (s *ShadowsocksProxy) startUDP() error { log.Err(err) return } - // logging.Info("udp %s <----> %s", raddr, tgtAddr) tgtUDPAddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { logging.Error("failed to resolve target UDP address: %v", err) diff --git a/utils/config.go b/utils/config.go deleted file mode 100644 index ce0ab30..0000000 --- a/utils/config.go +++ /dev/null @@ -1,128 +0,0 @@ -package utils - -import ( - "encoding/json" - "io/ioutil" - "os" - "strconv" -) - -type Config struct { - File string - Map ConfigMap -} - -type ConfigMap map[string]interface{} - -var ConfigInstance map[string]*Config - -func init() { - ConfigInstance = make(map[string]*Config) -} - -func ConfigFactory(file string) (config *Config) { - if ConfigInstance[file] != nil { - return ConfigInstance[file] - } - config = &Config{ - File: file, - Map: ConfigMap{}, - } - if err := config.ReadConfig(); err != nil { - panic("can not read file") - } - return config -} - -func (this *Config) ReadConfig() error { - if IsFileExist(this.File) { - result, err := ioutil.ReadFile(this.File) - if err != nil { - return err - } - if err := json.Unmarshal(result, &this.Map); err != nil { - return err - } - return nil - } else { - return nil - } -} - -func (this *Config) WriteConfig() error { - file, err := os.OpenFile(this.File, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) - if err != nil { - return err - } - result, err := json.MarshalIndent(this.Map, "", " ") - if err != nil { - return err - } - w, err := file.Write(result) - if err != nil && w < 0 { - return err - } - return nil -} - -func (this ConfigMap) GetInt(name string) int { - value := this[name] - if value == nil { - return 0 - } - switch value.(type) { - case float64: - return int(value.(float64)) - case string: - result, err := strconv.Atoi(value.(string)) - if err != nil { - panic(err) - } - return result - default: - return 0 - } -} - -func (this ConfigMap) GetString(name string) string { - value := this[name] - if value == nil { - return "" - } - switch value.(type) { - case float64: - return strconv.Itoa(int(value.(float64))) - case string: - return value.(string) - default: - return "0" - } -} - -func (this ConfigMap) GetConfigMap(name string) ConfigMap { - value := this[name] - if value == nil { - return nil - } - return ConfigMap(this[name].(map[string]interface{})) -} - -func (this ConfigMap) PutInt(key string, value int) { - this[key] = value -} - -func (this ConfigMap) PutString(key string, value string) { - this[key] = value -} - -func (this ConfigMap) PutConfigMap(key string, value ConfigMap) { - this[key] = value -} - -func (this ConfigMap) String() string { - result, err := json.Marshal(this) - if err != nil { - panic(err) - } - return string(result) -} diff --git a/utils/config_test.go b/utils/config_test.go deleted file mode 100644 index fe4cde9..0000000 --- a/utils/config_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package utils - -import ( - "fmt" - "testing" -) - -func Test_Config(t *testing.T) { - config, err := ConfigFactory("../config.json") - if err != nil { - fmt.Println(err) - return - } - config.Map.PutString("sakura", "killer") - config.Map.PutInt("abc", 1) - subMap := ConfigMap{} - subMap.PutString("funck", "avc") - config.Map.PutConfigMap("subMap", subMap) - config.WriteConfig() -} - -func Test_ConfigRead(t *testing.T) { - defer func() { - if err := recover(); err != nil { - fmt.Println(err) - } - }() - config, err := ConfigFactory("../config.json") - if err != nil { - fmt.Println(err) - return - } - fmt.Println(config.Map.GetInt("abc")) - fmt.Println(config.Map.GetInt("bcd")) - fmt.Println(config.Map.GetString("bcd")) - fmt.Println(config.Map.GetConfigMap("bcd")) - fmt.Println(config.Map.GetString("sakura")) - fmt.Println(config.Map.GetConfigMap("subMap").GetString("funck")) -} diff --git a/utils/io_test.go b/utils/iox/io_test.go similarity index 98% rename from utils/io_test.go rename to utils/iox/io_test.go index 7ec7906..c4eabf5 100644 --- a/utils/io_test.go +++ b/utils/iox/io_test.go @@ -1,4 +1,4 @@ -package utils +package iox import ( "os" diff --git a/utils/io.go b/utils/iox/iox.go similarity index 95% rename from utils/io.go rename to utils/iox/iox.go index 0249920..ce0a395 100644 --- a/utils/io.go +++ b/utils/iox/iox.go @@ -1,4 +1,4 @@ -package utils +package iox import ( "os" diff --git a/utils/time.go b/utils/time.go index 67b50b1..2713ffe 100644 --- a/utils/time.go +++ b/utils/time.go @@ -40,7 +40,7 @@ import ( // Format formats a date based on joda conventions for performance this method recommended to be used func Format(format string, date time.Time) string { - formatRune := []rune(format) + formatRune := []byte(format) lenFormat := len(formatRune) out := "" for i := 0; i < len(formatRune); i++ { @@ -435,7 +435,7 @@ func Format(format string, date time.Time) string { continue } - tmp := []rune{} + tmp := []byte{} j := 1 for ; i+j < lenFormat; j++ { if formatRune[i+j] != r { diff --git a/utils/time_test.go b/utils/time_test.go index bab0715..0b995fc 100644 --- a/utils/time_test.go +++ b/utils/time_test.go @@ -15,11 +15,23 @@ func Benchmark_Format(t *testing.B) { for i := 0; i < t.N; i++ { Format("yyyy-MM-dd HH:mm:ss", time.Now()) } + t.Log(Format("yyyy-MM-dd HH:mm:ss", time.Now())) + t.ReportAllocs() +} + +func Benchmark_format_string(t *testing.B) { + a := []byte{0x45, 0x46} + t.ResetTimer() + for i := 1; i < t.N; i++ { + _ = string(a) + } + t.ReportAllocs() } func Benchmark_OriginFormat(t *testing.B) { t.ResetTimer() for i := 0; i < t.N; i++ { - time.Now().Format("06") + time.Now().Format("2006-01-02 15:04:05") } + t.ReportAllocs() }