소스 검색

Db file change

刘河 6 년 전
부모
커밋
5fd335f330
17개의 변경된 파일597개의 추가작업 그리고 567개의 파일을 삭제
  1. 18 18
      bridge/bridge.go
  2. 10 0
      lib/common/util.go
  3. 0 1
      lib/config/config.go
  4. 17 17
      lib/conn/conn.go
  5. 0 4
      lib/crypt/crypt.go
  6. 0 35
      lib/file/csv.go
  7. 356 0
      lib/file/db.go
  8. 26 338
      lib/file/file.go
  9. 36 36
      lib/file/obj.go
  10. 3 3
      server/proxy/http.go
  11. 37 81
      server/server.go
  12. 1 1
      server/test/test.go
  13. 61 1
      server/tool/utils.go
  14. 2 2
      web/controllers/base.go
  15. 10 10
      web/controllers/client.go
  16. 19 19
      web/controllers/index.go
  17. 1 1
      web/controllers/login.go

+ 18 - 18
bridge/bridge.go

@@ -90,7 +90,7 @@ func (s *Bridge) GetHealthFromClient(id int, c *conn.Conn) {
 		if info, status, err := c.GetHealthInfo(); err != nil {
 			break
 		} else if !status { //the status is true , return target to the targetArr
-			file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+			file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 				v := value.(*file.Tunnel)
 				if v.Client.Id == id && v.Mode == "tcp" && strings.Contains(v.Target.TargetStr, info) {
 					v.Lock()
@@ -106,7 +106,7 @@ func (s *Bridge) GetHealthFromClient(id int, c *conn.Conn) {
 				}
 				return true
 			})
-			file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+			file.GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 				v := value.(*file.Host)
 				if v.Client.Id == id && strings.Contains(v.Target.TargetStr, info) {
 					v.Lock()
@@ -123,7 +123,7 @@ func (s *Bridge) GetHealthFromClient(id int, c *conn.Conn) {
 				return true
 			})
 		} else { //the status is false,remove target from the targetArr
-			file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+			file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 				v := value.(*file.Tunnel)
 				if v.Client.Id == id && v.Mode == "tcp" && common.IsArrContains(v.HealthRemoveArr, info) && !common.IsArrContains(v.Target.TargetArr, info) {
 					v.Lock()
@@ -134,7 +134,7 @@ func (s *Bridge) GetHealthFromClient(id int, c *conn.Conn) {
 				return true
 			})
 
-			file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+			file.GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 				v := value.(*file.Host)
 				if v.Client.Id == id && common.IsArrContains(v.HealthRemoveArr, info) && !common.IsArrContains(v.Target.TargetArr, info) {
 					v.Lock()
@@ -182,7 +182,7 @@ func (s *Bridge) cliProcess(c *conn.Conn) {
 		return
 	}
 	//verify
-	id, err := file.GetCsvDb().GetIdByVerifyKey(string(buf), c.Conn.RemoteAddr().String())
+	id, err := file.GetDb().GetIdByVerifyKey(string(buf), c.Conn.RemoteAddr().String())
 	if err != nil {
 		logs.Info("Current client connection validation error, close this client:", c.Conn.RemoteAddr())
 		s.verifyError(c)
@@ -204,10 +204,10 @@ func (s *Bridge) DelClient(id int) {
 			v.(*Client).signal.Close()
 		}
 		s.Client.Delete(id)
-		if file.GetCsvDb().IsPubClient(id) {
+		if file.GetDb().IsPubClient(id) {
 			return
 		}
-		if c, err := file.GetCsvDb().GetClient(id); err == nil {
+		if c, err := file.GetDb().GetClient(id); err == nil {
 			s.CloseClient <- c.Id
 		}
 	}
@@ -215,7 +215,7 @@ func (s *Bridge) DelClient(id int) {
 
 //use different
 func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
-	isPub := file.GetCsvDb().IsPubClient(id)
+	isPub := file.GetDb().IsPubClient(id)
 	switch typeVal {
 	case common.WORK_MAIN:
 		if isPub {
@@ -237,7 +237,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
 			v.(*Client).tunnel = muxConn
 		}
 	case common.WORK_CONFIG:
-		client, err := file.GetCsvDb().GetClient(id)
+		client, err := file.GetDb().GetClient(id)
 		if err != nil || (!isPub && !client.ConfigConnAllow) {
 			c.Close()
 			return
@@ -259,7 +259,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
 		//read md5 secret
 		if b, err := c.GetShortContent(32); err != nil {
 			return
-		} else if t := file.GetCsvDb().GetTaskByMd5Password(string(b)); t == nil {
+		} else if t := file.GetDb().GetTaskByMd5Password(string(b)); t == nil {
 			return
 		} else {
 			if v, ok := s.Client.Load(t.Client.Id); !ok {
@@ -373,18 +373,18 @@ loop:
 				break loop
 			} else {
 				var str string
-				id, err := file.GetCsvDb().GetClientIdByVkey(string(b))
+				id, err := file.GetDb().GetClientIdByVkey(string(b))
 				if err != nil {
 					break loop
 				}
-				file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+				file.GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 					v := value.(*file.Host)
 					if v.Client.Id == id {
 						str += v.Remark + common.CONN_DATA_SEQ
 					}
 					return true
 				})
-				file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+				file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 					v := value.(*file.Tunnel)
 					if _, ok := s.runList[v.Id]; ok && v.Client.Id == id {
 						str += v.Remark + common.CONN_DATA_SEQ
@@ -401,7 +401,7 @@ loop:
 				c.WriteAddFail()
 				break loop
 			} else {
-				if err = file.GetCsvDb().NewClient(client); err != nil {
+				if err = file.GetDb().NewClient(client); err != nil {
 					fail = true
 					c.WriteAddFail()
 					break loop
@@ -422,12 +422,12 @@ loop:
 				h.Location = "/"
 			}
 			if !client.HasHost(h) {
-				if file.GetCsvDb().IsHostExist(h) {
+				if file.GetDb().IsHostExist(h) {
 					fail = true
 					c.WriteAddFail()
 					break loop
 				} else {
-					file.GetCsvDb().NewHost(h)
+					file.GetDb().NewHost(h)
 					c.WriteAddOk()
 				}
 			} else {
@@ -469,7 +469,7 @@ loop:
 							tl.Target.TargetStr = strconv.Itoa(targets[i])
 						}
 					}
-					tl.Id = int(file.GetCsvDb().GetTaskId())
+					tl.Id = int(file.GetDb().JsonDb.GetTaskId())
 					tl.Status = true
 					tl.Flow = new(file.Flow)
 					tl.NoStore = true
@@ -478,7 +478,7 @@ loop:
 					tl.LocalPath = t.LocalPath
 					tl.StripPre = t.StripPre
 					if !client.HasTunnel(tl) {
-						if err := file.GetCsvDb().NewTask(tl); err != nil {
+						if err := file.GetDb().NewTask(tl); err != nil {
 							logs.Notice("Add task error ", err.Error())
 							fail = true
 							c.WriteAddFail()

+ 10 - 0
lib/common/util.go

@@ -15,6 +15,7 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+	"sync"
 )
 
 //Get the corresponding IP address through domain name
@@ -344,3 +345,12 @@ func BytesToNum(b []byte) int {
 	x, _ := strconv.Atoi(str)
 	return int(x)
 }
+
+func GeSynctMapLen(m sync.Map) int {
+	var c int
+	m.Range(func(key, value interface{}) bool {
+		c++
+		return true
+	})
+	return c
+}

+ 0 - 1
lib/config/config.go

@@ -93,7 +93,6 @@ func NewConfig(path string) (c *Config, err error) {
 				}
 			}
 		}
-
 	}
 	return
 }

+ 17 - 17
lib/conn/conn.go

@@ -210,21 +210,6 @@ func (s *Conn) SendHostInfo(h *file.Host) (int, error) {
 	return s.Write(raw.Bytes())
 }
 
-//get task or host result of add
-func (s *Conn) GetAddStatus() (b bool) {
-	binary.Read(s.Conn, binary.LittleEndian, &b)
-	return
-}
-
-func (s *Conn) WriteAddOk() error {
-	return binary.Write(s.Conn, binary.LittleEndian, true)
-}
-
-func (s *Conn) WriteAddFail() error {
-	defer s.Close()
-	return binary.Write(s.Conn, binary.LittleEndian, false)
-}
-
 //get task info
 func (s *Conn) GetHostInfo() (h *file.Host, err error) {
 	var l int
@@ -238,7 +223,7 @@ func (s *Conn) GetHostInfo() (h *file.Host, err error) {
 		arr := strings.Split(string(buf[:l]), common.CONN_DATA_SEQ)
 		h = new(file.Host)
 		h.Target = new(file.Target)
-		h.Id = int(file.GetCsvDb().GetHostId())
+		h.Id = int(file.GetDb().JsonDb.GetHostId())
 		h.Host = arr[0]
 		h.Target.TargetStr = arr[1]
 		h.HeaderChange = arr[2]
@@ -328,7 +313,7 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
 		t.Mode = arr[0]
 		t.Ports = arr[1]
 		t.Target.TargetStr = arr[2]
-		t.Id = int(file.GetCsvDb().GetTaskId())
+		t.Id = int(file.GetDb().JsonDb.GetTaskId())
 		t.Status = true
 		t.Flow = new(file.Flow)
 		t.Remark = arr[3]
@@ -379,6 +364,21 @@ func (s *Conn) WriteChan() (int, error) {
 	return s.Write([]byte(common.WORK_CHAN))
 }
 
+//get task or host result of add
+func (s *Conn) GetAddStatus() (b bool) {
+	binary.Read(s.Conn, binary.LittleEndian, &b)
+	return
+}
+
+func (s *Conn) WriteAddOk() error {
+	return binary.Write(s.Conn, binary.LittleEndian, true)
+}
+
+func (s *Conn) WriteAddFail() error {
+	defer s.Close()
+	return binary.Write(s.Conn, binary.LittleEndian, false)
+}
+
 //get the assembled amount data(len 4 and content)
 func GetLenBytes(buf []byte) (b []byte, err error) {
 	raw := bytes.NewBuffer([]byte{})

+ 0 - 4
lib/crypt/crypt.go

@@ -19,11 +19,8 @@ func AesEncrypt(origData, key []byte) ([]byte, error) {
 	}
 	blockSize := block.BlockSize()
 	origData = PKCS5Padding(origData, blockSize)
-	// origData = ZeroPadding(origData, block.BlockSize())
 	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
 	crypted := make([]byte, len(origData))
-	// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
-	// crypted := origData
 	blockMode.CryptBlocks(crypted, origData)
 	return crypted, nil
 }
@@ -52,7 +49,6 @@ func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
 //Remove excess
 func PKCS5UnPadding(origData []byte) (error, []byte) {
 	length := len(origData)
-	// 去掉最后一个字节 unpadding 次
 	unpadding := int(origData[length-1])
 	if (length - unpadding) < 0 {
 		return errors.New("len error"), nil

+ 0 - 35
lib/file/csv.go

@@ -1,35 +0,0 @@
-package file
-
-import (
-	"github.com/cnlh/nps/lib/common"
-	"sort"
-	"sync"
-)
-
-var (
-	CsvDb *Csv
-	once  sync.Once
-)
-
-//init csv from file
-func GetCsvDb() *Csv {
-	once.Do(func() {
-		CsvDb = NewCsv(common.GetRunPath())
-		CsvDb.LoadClientFromCsv()
-		CsvDb.LoadTaskFromCsv()
-		CsvDb.LoadHostFromCsv()
-	})
-	return CsvDb
-}
-
-func GetMapKeys(m sync.Map, isSort bool, sortKey, order string) (keys []int) {
-	if sortKey != "" && isSort {
-		return sortClientByKey(m, sortKey, order)
-	}
-	m.Range(func(key, value interface{}) bool {
-		keys = append(keys, key.(int))
-		return true
-	})
-	sort.Ints(keys)
-	return
-}

+ 356 - 0
lib/file/db.go

@@ -0,0 +1,356 @@
+package file
+
+import (
+	"errors"
+	"fmt"
+	"github.com/cnlh/nps/lib/common"
+	"github.com/cnlh/nps/lib/crypt"
+	"github.com/cnlh/nps/lib/rate"
+	"net/http"
+	"regexp"
+	"sort"
+	"strings"
+	"sync"
+)
+
+type DbUtils struct {
+	JsonDb *JsonDb
+}
+
+var (
+	Db   *DbUtils
+	once sync.Once
+)
+
+//init csv from file
+func GetDb() *DbUtils {
+	once.Do(func() {
+		jsonDb := NewJsonDb(common.GetRunPath())
+		jsonDb.LoadClientFromJsonFile()
+		jsonDb.LoadTaskFromJsonFile()
+		jsonDb.LoadHostFromJsonFile()
+		Db = &DbUtils{JsonDb: jsonDb}
+	})
+	return Db
+}
+
+func GetMapKeys(m sync.Map, isSort bool, sortKey, order string) (keys []int) {
+	if sortKey != "" && isSort {
+		return sortClientByKey(m, sortKey, order)
+	}
+	m.Range(func(key, value interface{}) bool {
+		keys = append(keys, key.(int))
+		return true
+	})
+	sort.Ints(keys)
+	return
+}
+
+func (s *DbUtils) GetClientList(start, length int, search, sort, order string, clientId int) ([]*Client, int) {
+	list := make([]*Client, 0)
+	var cnt int
+	keys := GetMapKeys(s.JsonDb.Clients, true, sort, order)
+	for _, key := range keys {
+		if value, ok := s.JsonDb.Clients.Load(key); ok {
+			v := value.(*Client)
+			if v.NoDisplay {
+				continue
+			}
+			if clientId != 0 && clientId != v.Id {
+				continue
+			}
+			if search != "" && !(v.Id == common.GetIntNoErrByStr(search) || strings.Contains(v.VerifyKey, search) || strings.Contains(v.Remark, search)) {
+				continue
+			}
+			cnt++
+			if start--; start < 0 {
+				if length--; length > 0 {
+					list = append(list, v)
+				}
+			}
+		}
+	}
+	return list, cnt
+}
+
+func (s *DbUtils) GetIdByVerifyKey(vKey string, addr string) (id int, err error) {
+	var exist bool
+	s.JsonDb.Clients.Range(func(key, value interface{}) bool {
+		v := value.(*Client)
+		if common.Getverifyval(v.VerifyKey) == vKey && v.Status {
+			v.Addr = common.GetIpByAddr(addr)
+			id = v.Id
+			exist = true
+			return false
+		}
+		return true
+	})
+	if exist {
+		return
+	}
+	return 0, errors.New("not found")
+}
+
+func (s *DbUtils) NewTask(t *Tunnel) (err error) {
+	s.JsonDb.Tasks.Range(func(key, value interface{}) bool {
+		v := value.(*Tunnel)
+		if (v.Mode == "secret" || v.Mode == "p2p") && v.Password == t.Password {
+			err = errors.New(fmt.Sprintf("secret mode keys %s must be unique", t.Password))
+			return false
+		}
+		return true
+	})
+	if err != nil {
+		return
+	}
+	t.Flow = new(Flow)
+	s.JsonDb.Tasks.Store(t.Id, t)
+	s.JsonDb.StoreTasksToJsonFile()
+	return
+}
+
+func (s *DbUtils) UpdateTask(t *Tunnel) error {
+	s.JsonDb.Tasks.Store(t.Id, t)
+	s.JsonDb.StoreTasksToJsonFile()
+	return nil
+}
+
+func (s *DbUtils) DelTask(id int) error {
+	s.JsonDb.Tasks.Delete(id)
+	s.JsonDb.StoreTasksToJsonFile()
+	return nil
+}
+
+//md5 password
+func (s *DbUtils) GetTaskByMd5Password(p string) (t *Tunnel) {
+	s.JsonDb.Tasks.Range(func(key, value interface{}) bool {
+		if crypt.Md5(value.(*Tunnel).Password) == p {
+			t = value.(*Tunnel)
+			return false
+		}
+		return true
+	})
+	return
+}
+
+func (s *DbUtils) GetTask(id int) (t *Tunnel, err error) {
+	if v, ok := s.JsonDb.Tasks.Load(id); ok {
+		t = v.(*Tunnel)
+		return
+	}
+	err = errors.New("not found")
+	return
+}
+
+func (s *DbUtils) DelHost(id int) error {
+	s.JsonDb.Hosts.Delete(id)
+	s.JsonDb.StoreHostToJsonFile()
+	return nil
+}
+
+func (s *DbUtils) IsHostExist(h *Host) bool {
+	var exist bool
+	s.JsonDb.Hosts.Range(func(key, value interface{}) bool {
+		v := value.(*Host)
+		if v.Id != h.Id && v.Host == h.Host && h.Location == v.Location && (v.Scheme == "all" || v.Scheme == h.Scheme) {
+			exist = true
+			return false
+		}
+		return true
+	})
+	return exist
+}
+
+func (s *DbUtils) NewHost(t *Host) error {
+	if t.Location == "" {
+		t.Location = "/"
+	}
+	if s.IsHostExist(t) {
+		return errors.New("host has exist")
+	}
+	t.Flow = new(Flow)
+	s.JsonDb.Hosts.Store(t.Id, t)
+	s.JsonDb.StoreHostToJsonFile()
+	return nil
+}
+
+func (s *DbUtils) GetHost(start, length int, id int, search string) ([]*Host, int) {
+	list := make([]*Host, 0)
+	var cnt int
+	keys := GetMapKeys(s.JsonDb.Hosts, false, "", "")
+	for _, key := range keys {
+		if value, ok := s.JsonDb.Hosts.Load(key); ok {
+			v := value.(*Host)
+			if search != "" && !(v.Id == common.GetIntNoErrByStr(search) || strings.Contains(v.Host, search) || strings.Contains(v.Remark, search)) {
+				continue
+			}
+			if id == 0 || v.Client.Id == id {
+				cnt++
+				if start--; start < 0 {
+					if length--; length > 0 {
+						list = append(list, v)
+					}
+				}
+			}
+		}
+	}
+	return list, cnt
+}
+
+func (s *DbUtils) DelClient(id int) error {
+	s.JsonDb.Clients.Delete(id)
+	s.JsonDb.StoreClientsToJsonFile()
+	return nil
+}
+
+func (s *DbUtils) NewClient(c *Client) error {
+	var isNotSet bool
+	if c.WebUserName != "" && !s.VerifyUserName(c.WebUserName, c.Id) {
+		return errors.New("web login username duplicate, please reset")
+	}
+reset:
+	if c.VerifyKey == "" || isNotSet {
+		isNotSet = true
+		c.VerifyKey = crypt.GetRandomString(16)
+	}
+	if c.RateLimit == 0 {
+		c.Rate = rate.NewRate(int64(2 << 23))
+		c.Rate.Start()
+	}
+	if !s.VerifyVkey(c.VerifyKey, c.Id) {
+		if isNotSet {
+			goto reset
+		}
+		return errors.New("Vkey duplicate, please reset")
+	}
+	if c.Id == 0 {
+		c.Id = int(s.JsonDb.GetClientId())
+	}
+	if c.Flow == nil {
+		c.Flow = new(Flow)
+	}
+	s.JsonDb.Clients.Store(c.Id, c)
+	s.JsonDb.StoreClientsToJsonFile()
+	return nil
+}
+
+func (s *DbUtils) VerifyVkey(vkey string, id int) (res bool) {
+	res = true
+	s.JsonDb.Clients.Range(func(key, value interface{}) bool {
+		v := value.(*Client)
+		if v.VerifyKey == vkey && v.Id != id {
+			res = false
+			return false
+		}
+		return true
+	})
+	return res
+}
+
+func (s *DbUtils) VerifyUserName(username string, id int) (res bool) {
+	res = true
+	s.JsonDb.Clients.Range(func(key, value interface{}) bool {
+		v := value.(*Client)
+		if v.WebUserName == username && v.Id != id {
+			res = false
+			return false
+		}
+		return true
+	})
+	return res
+}
+
+func (s *DbUtils) UpdateClient(t *Client) error {
+	s.JsonDb.Clients.Store(t.Id, t)
+	if t.RateLimit == 0 {
+		t.Rate = rate.NewRate(int64(2 << 23))
+		t.Rate.Start()
+	}
+	return nil
+}
+
+func (s *DbUtils) IsPubClient(id int) bool {
+	client, err := s.GetClient(id)
+	if err == nil {
+		return client.NoDisplay
+	}
+	return false
+}
+
+func (s *DbUtils) GetClient(id int) (c *Client, err error) {
+	if v, ok := s.JsonDb.Clients.Load(id); ok {
+		c = v.(*Client)
+		return
+	}
+	err = errors.New("未找到客户端")
+	return
+}
+
+func (s *DbUtils) GetClientIdByVkey(vkey string) (id int, err error) {
+	var exist bool
+	s.JsonDb.Clients.Range(func(key, value interface{}) bool {
+		v := value.(*Client)
+		if crypt.Md5(v.VerifyKey) == vkey {
+			exist = true
+			id = v.Id
+			return false
+		}
+		return true
+	})
+	if exist {
+		return
+	}
+	err = errors.New("未找到客户端")
+	return
+}
+
+func (s *DbUtils) GetHostById(id int) (h *Host, err error) {
+	if v, ok := s.JsonDb.Hosts.Load(id); ok {
+		h = v.(*Host)
+		return
+	}
+	err = errors.New("The host could not be parsed")
+	return
+}
+
+//get key by host from x
+func (s *DbUtils) GetInfoByHost(host string, r *http.Request) (h *Host, err error) {
+	var hosts []*Host
+	//Handling Ported Access
+	host = common.GetIpByAddr(host)
+	s.JsonDb.Hosts.Range(func(key, value interface{}) bool {
+		v := value.(*Host)
+		if v.IsClose {
+			return true
+		}
+		//Remove http(s) http(s)://a.proxy.com
+		//*.proxy.com *.a.proxy.com  Do some pan-parsing
+		tmp := strings.Replace(v.Host, "*", `\w+?`, -1)
+		var re *regexp.Regexp
+		if re, err = regexp.Compile(tmp); err != nil {
+			return true
+		}
+		if len(re.FindAllString(host, -1)) > 0 && (v.Scheme == "all" || v.Scheme == r.URL.Scheme) {
+			//URL routing
+			hosts = append(hosts, v)
+		}
+		return true
+	})
+
+	for _, v := range hosts {
+		//If not set, default matches all
+		if v.Location == "" {
+			v.Location = "/"
+		}
+		if strings.Index(r.RequestURI, v.Location) == 0 {
+			if h == nil || (len(v.Location) > len(h.Location)) {
+				h = v
+			}
+		}
+	}
+	if h != nil {
+		return
+	}
+	err = errors.New("The host could not be parsed")
+	return
+}

+ 26 - 338
lib/file/file.go

@@ -3,21 +3,17 @@ package file
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"github.com/cnlh/nps/lib/common"
-	"github.com/cnlh/nps/lib/crypt"
 	"github.com/cnlh/nps/lib/rate"
-	"net/http"
 	"os"
 	"path/filepath"
-	"regexp"
 	"strings"
 	"sync"
 	"sync/atomic"
 )
 
-func NewCsv(runPath string) *Csv {
-	return &Csv{
+func NewJsonDb(runPath string) *JsonDb {
+	return &JsonDb{
 		RunPath:        runPath,
 		TaskFilePath:   filepath.Join(runPath, "conf", "tasks.json"),
 		HostFilePath:   filepath.Join(runPath, "conf", "hosts.json"),
@@ -25,21 +21,21 @@ func NewCsv(runPath string) *Csv {
 	}
 }
 
-type Csv struct {
+type JsonDb struct {
 	Tasks            sync.Map
-	Hosts            sync.Map //域名列表
+	Hosts            sync.Map
 	HostsTmp         sync.Map
-	Clients          sync.Map //客户端
-	RunPath          string   //存储根目录
-	ClientIncreaseId int32    //客户端id
-	TaskIncreaseId   int32    //任务自增ID
-	HostIncreaseId   int32    //host increased id
-	TaskFilePath     string
-	HostFilePath     string
-	ClientFilePath   string
+	Clients          sync.Map
+	RunPath          string
+	ClientIncreaseId int32  //client increased id
+	TaskIncreaseId   int32  //task increased id
+	HostIncreaseId   int32  //host increased id
+	TaskFilePath     string //task file path
+	HostFilePath     string //host file path
+	ClientFilePath   string //client file path
 }
 
-func (s *Csv) LoadTaskFromCsv() {
+func (s *JsonDb) LoadTaskFromJsonFile() {
 	loadSyncMapFromFile(s.TaskFilePath, func(v string) {
 		var err error
 		post := new(Tunnel)
@@ -56,7 +52,7 @@ func (s *Csv) LoadTaskFromCsv() {
 	})
 }
 
-func (s *Csv) LoadClientFromCsv() {
+func (s *JsonDb) LoadClientFromJsonFile() {
 	loadSyncMapFromFile(s.ClientFilePath, func(v string) {
 		post := new(Client)
 		if json.Unmarshal([]byte(v), &post) != nil {
@@ -68,6 +64,7 @@ func (s *Csv) LoadClientFromCsv() {
 			post.Rate = rate.NewRate(int64(2 << 23))
 		}
 		post.Rate.Start()
+		post.NowConn = 0
 		s.Clients.Store(post.Id, post)
 		if post.Id > int(s.ClientIncreaseId) {
 			s.ClientIncreaseId = int32(post.Id)
@@ -75,7 +72,7 @@ func (s *Csv) LoadClientFromCsv() {
 	})
 }
 
-func (s *Csv) LoadHostFromCsv() {
+func (s *JsonDb) LoadHostFromJsonFile() {
 	loadSyncMapFromFile(s.HostFilePath, func(v string) {
 		var err error
 		post := new(Host)
@@ -92,259 +89,7 @@ func (s *Csv) LoadHostFromCsv() {
 	})
 }
 
-func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (id int, err error) {
-	var exist bool
-	s.Clients.Range(func(key, value interface{}) bool {
-		v := value.(*Client)
-		if common.Getverifyval(v.VerifyKey) == vKey && v.Status {
-			v.Addr = common.GetIpByAddr(addr)
-			id = v.Id
-			exist = true
-			return false
-		}
-		return true
-	})
-	if exist {
-		return
-	}
-	return 0, errors.New("not found")
-}
-
-func (s *Csv) NewTask(t *Tunnel) (err error) {
-	s.Tasks.Range(func(key, value interface{}) bool {
-		v := value.(*Tunnel)
-		if (v.Mode == "secret" || v.Mode == "p2p") && v.Password == t.Password {
-			err = errors.New(fmt.Sprintf("Secret mode keys %s must be unique", t.Password))
-			return false
-		}
-		return true
-	})
-	if err != nil {
-		return
-	}
-	t.Flow = new(Flow)
-	s.Tasks.Store(t.Id, t)
-	s.StoreTasksToCsv()
-	return
-}
-
-func (s *Csv) UpdateTask(t *Tunnel) error {
-	s.Tasks.Store(t.Id, t)
-	s.StoreTasksToCsv()
-	return nil
-}
-
-func (s *Csv) DelTask(id int) error {
-	s.Tasks.Delete(id)
-	s.StoreTasksToCsv()
-	return nil
-}
-
-//md5 password
-func (s *Csv) GetTaskByMd5Password(p string) (t *Tunnel) {
-	s.Tasks.Range(func(key, value interface{}) bool {
-		if crypt.Md5(value.(*Tunnel).Password) == p {
-			t = value.(*Tunnel)
-			return false
-		}
-		return true
-	})
-	return
-}
-
-func (s *Csv) GetTask(id int) (t *Tunnel, err error) {
-	if v, ok := s.Tasks.Load(id); ok {
-		t = v.(*Tunnel)
-		return
-	}
-	err = errors.New("not found")
-	return
-}
-
-func (s *Csv) StoreHostToCsv() {
-	storeSyncMapToFile(s.Hosts, s.HostFilePath)
-}
-
-func (s *Csv) StoreTasksToCsv() {
-	storeSyncMapToFile(s.Tasks, s.TaskFilePath)
-}
-
-func (s *Csv) StoreClientsToCsv() {
-	storeSyncMapToFile(s.Clients, s.ClientFilePath)
-}
-
-func (s *Csv) DelHost(id int) error {
-	s.Hosts.Delete(id)
-	s.StoreHostToCsv()
-	return nil
-}
-
-func (s *Csv) GetMapLen(m sync.Map) int {
-	var c int
-	m.Range(func(key, value interface{}) bool {
-		c++
-		return true
-	})
-	return c
-}
-
-func (s *Csv) IsHostExist(h *Host) bool {
-	var exist bool
-	s.Hosts.Range(func(key, value interface{}) bool {
-		v := value.(*Host)
-		if v.Host == h.Host && h.Location == v.Location && (v.Scheme == "all" || v.Scheme == h.Scheme) {
-			exist = true
-			return false
-		}
-		return true
-	})
-	return exist
-}
-
-func (s *Csv) NewHost(t *Host) error {
-	if t.Location == "" {
-		t.Location = "/"
-	}
-	if s.IsHostExist(t) {
-		return errors.New("host has exist")
-	}
-	t.Flow = new(Flow)
-	s.Hosts.Store(t.Id, t)
-	s.StoreHostToCsv()
-	return nil
-}
-
-func (s *Csv) GetHost(start, length int, id int, search string) ([]*Host, int) {
-	list := make([]*Host, 0)
-	var cnt int
-	keys := GetMapKeys(s.Hosts, false, "", "")
-	for _, key := range keys {
-		if value, ok := s.Hosts.Load(key); ok {
-			v := value.(*Host)
-			if search != "" && !(v.Id == common.GetIntNoErrByStr(search) || strings.Contains(v.Host, search) || strings.Contains(v.Remark, search)) {
-				continue
-			}
-			if id == 0 || v.Client.Id == id {
-				cnt++
-				if start--; start < 0 {
-					if length--; length > 0 {
-						list = append(list, v)
-					}
-				}
-			}
-		}
-	}
-	return list, cnt
-}
-
-func (s *Csv) DelClient(id int) error {
-	s.Clients.Delete(id)
-	s.StoreClientsToCsv()
-	return nil
-}
-
-func (s *Csv) NewClient(c *Client) error {
-	var isNotSet bool
-	if c.WebUserName != "" && !s.VerifyUserName(c.WebUserName, c.Id) {
-		return errors.New("web login username duplicate, please reset")
-	}
-reset:
-	if c.VerifyKey == "" || isNotSet {
-		isNotSet = true
-		c.VerifyKey = crypt.GetRandomString(16)
-	}
-	if c.RateLimit == 0 {
-		c.Rate = rate.NewRate(int64(2 << 23))
-		c.Rate.Start()
-	}
-	if !s.VerifyVkey(c.VerifyKey, c.Id) {
-		if isNotSet {
-			goto reset
-		}
-		return errors.New("Vkey duplicate, please reset")
-	}
-	if c.Id == 0 {
-		c.Id = int(s.GetClientId())
-	}
-	if c.Flow == nil {
-		c.Flow = new(Flow)
-	}
-	s.Clients.Store(c.Id, c)
-	s.StoreClientsToCsv()
-	return nil
-}
-
-func (s *Csv) VerifyVkey(vkey string, id int) (res bool) {
-	res = true
-	s.Clients.Range(func(key, value interface{}) bool {
-		v := value.(*Client)
-		if v.VerifyKey == vkey && v.Id != id {
-			res = false
-			return false
-		}
-		return true
-	})
-	return res
-}
-
-func (s *Csv) VerifyUserName(username string, id int) (res bool) {
-	res = true
-	s.Clients.Range(func(key, value interface{}) bool {
-		v := value.(*Client)
-		if v.WebUserName == username && v.Id != id {
-			res = false
-			return false
-		}
-		return true
-	})
-	return res
-}
-
-func (s *Csv) UpdateClient(t *Client) error {
-	s.Clients.Store(t.Id, t)
-	if t.RateLimit == 0 {
-		t.Rate = rate.NewRate(int64(2 << 23))
-		t.Rate.Start()
-	}
-	return nil
-}
-
-func (s *Csv) GetClientList(start, length int, search, sort, order string, clientId int) ([]*Client, int) {
-	list := make([]*Client, 0)
-	var cnt int
-	keys := GetMapKeys(s.Clients, true, sort, order)
-	for _, key := range keys {
-		if value, ok := s.Clients.Load(key); ok {
-			v := value.(*Client)
-			if v.NoDisplay {
-				continue
-			}
-			if clientId != 0 && clientId != v.Id {
-				continue
-			}
-			if search != "" && !(v.Id == common.GetIntNoErrByStr(search) || strings.Contains(v.VerifyKey, search) || strings.Contains(v.Remark, search)) {
-				continue
-			}
-			cnt++
-			if start--; start < 0 {
-				if length--; length > 0 {
-					list = append(list, v)
-				}
-			}
-		}
-	}
-	return list, cnt
-}
-
-func (s *Csv) IsPubClient(id int) bool {
-	client, err := s.GetClient(id)
-	if err == nil {
-		return client.NoDisplay
-	}
-	return false
-}
-
-func (s *Csv) GetClient(id int) (c *Client, err error) {
+func (s *JsonDb) GetClient(id int) (c *Client, err error) {
 	if v, ok := s.Clients.Load(id); ok {
 		c = v.(*Client)
 		return
@@ -353,84 +98,27 @@ func (s *Csv) GetClient(id int) (c *Client, err error) {
 	return
 }
 
-func (s *Csv) GetClientIdByVkey(vkey string) (id int, err error) {
-	var exist bool
-	s.Clients.Range(func(key, value interface{}) bool {
-		v := value.(*Client)
-		if crypt.Md5(v.VerifyKey) == vkey {
-			exist = true
-			id = v.Id
-			return false
-		}
-		return true
-	})
-	if exist {
-		return
-	}
-	err = errors.New("未找到客户端")
-	return
+func (s *JsonDb) StoreHostToJsonFile() {
+	storeSyncMapToFile(s.Hosts, s.HostFilePath)
 }
 
-func (s *Csv) GetHostById(id int) (h *Host, err error) {
-	if v, ok := s.Hosts.Load(id); ok {
-		h = v.(*Host)
-		return
-	}
-	err = errors.New("The host could not be parsed")
-	return
+func (s *JsonDb) StoreTasksToJsonFile() {
+	storeSyncMapToFile(s.Tasks, s.TaskFilePath)
 }
 
-//get key by host from x
-func (s *Csv) GetInfoByHost(host string, r *http.Request) (h *Host, err error) {
-	var hosts []*Host
-	//Handling Ported Access
-	host = common.GetIpByAddr(host)
-	s.Hosts.Range(func(key, value interface{}) bool {
-		v := value.(*Host)
-		if v.IsClose {
-			return true
-		}
-		//Remove http(s) http(s)://a.proxy.com
-		//*.proxy.com *.a.proxy.com  Do some pan-parsing
-		tmp := strings.Replace(v.Host, "*", `\w+?`, -1)
-		var re *regexp.Regexp
-		if re, err = regexp.Compile(tmp); err != nil {
-			return true
-		}
-		if len(re.FindAllString(host, -1)) > 0 && (v.Scheme == "all" || v.Scheme == r.URL.Scheme) {
-			//URL routing
-			hosts = append(hosts, v)
-		}
-		return true
-	})
-
-	for _, v := range hosts {
-		//If not set, default matches all
-		if v.Location == "" {
-			v.Location = "/"
-		}
-		if strings.Index(r.RequestURI, v.Location) == 0 {
-			if h == nil || (len(v.Location) > len(h.Location)) {
-				h = v
-			}
-		}
-	}
-	if h != nil {
-		return
-	}
-	err = errors.New("The host could not be parsed")
-	return
+func (s *JsonDb) StoreClientsToJsonFile() {
+	storeSyncMapToFile(s.Clients, s.ClientFilePath)
 }
 
-func (s *Csv) GetClientId() int32 {
+func (s *JsonDb) GetClientId() int32 {
 	return atomic.AddInt32(&s.ClientIncreaseId, 1)
 }
 
-func (s *Csv) GetTaskId() int32 {
+func (s *JsonDb) GetTaskId() int32 {
 	return atomic.AddInt32(&s.TaskIncreaseId, 1)
 }
 
-func (s *Csv) GetHostId() int32 {
+func (s *JsonDb) GetHostId() int32 {
 	return atomic.AddInt32(&s.HostIncreaseId, 1)
 }
 

+ 36 - 36
lib/file/obj.go

@@ -23,6 +23,13 @@ func (s *Flow) Add(in, out int64) {
 	s.ExportFlow += int64(out)
 }
 
+type Config struct {
+	U        string
+	P        string
+	Compress bool
+	Crypt    bool
+}
+
 type Client struct {
 	Cnf             *Config
 	Id              int        //id
@@ -79,7 +86,7 @@ func (s *Client) GetConn() bool {
 }
 
 func (s *Client) HasTunnel(t *Tunnel) (exist bool) {
-	GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+	GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 		v := value.(*Tunnel)
 		if v.Client.Id == s.Id && v.Port == t.Port {
 			exist = true
@@ -92,7 +99,7 @@ func (s *Client) HasTunnel(t *Tunnel) (exist bool) {
 
 func (s *Client) HasHost(h *Host) bool {
 	var has bool
-	GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+	GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 		v := value.(*Host)
 		if v.Client.Id == s.Id && v.Host == h.Host && h.Location == v.Location {
 			has = true
@@ -104,17 +111,17 @@ func (s *Client) HasHost(h *Host) bool {
 }
 
 type Tunnel struct {
-	Id         int //Id
-	Port       int //服务端监听端口
+	Id         int
+	Port       int
 	ServerIp   string
-	Mode       string  //启动方式
-	Status     bool    //设置是否开启
-	RunStatus  bool    //当前运行状态
-	Client     *Client //所属客户端id
-	Ports      string  //客户端与服务端传递
+	Mode       string
+	Status     bool
+	RunStatus  bool
+	Client     *Client
+	Ports      string
 	Flow       *Flow
-	Password   string //私密模式密码,唯一
-	Remark     string //备注
+	Password   string
+	Remark     string
 	TargetAddr string
 	NoStore    bool
 	LocalPath  string
@@ -137,10 +144,27 @@ type Health struct {
 	sync.RWMutex
 }
 
+type Host struct {
+	Id           int
+	Host         string //host
+	HeaderChange string //header change
+	HostChange   string //host change
+	Location     string //url router
+	Remark       string //remark
+	Scheme       string //http https all
+	NoStore      bool
+	IsClose      bool
+	Flow         *Flow
+	Client       *Client
+	Target       *Target //目标
+	Health       `json:"-"`
+	sync.RWMutex
+}
+
 type Target struct {
 	nowIndex  int
 	TargetStr string
-	TargetArr []string //目标
+	TargetArr []string
 	sync.RWMutex
 }
 
@@ -162,27 +186,3 @@ func (s *Target) GetRandomTarget() (string, error) {
 	s.nowIndex++
 	return s.TargetArr[s.nowIndex], nil
 }
-
-type Config struct {
-	U        string
-	P        string
-	Compress bool
-	Crypt    bool
-}
-
-type Host struct {
-	Id           int
-	Host         string //host
-	HeaderChange string //header change
-	HostChange   string //host change
-	Location     string //url router
-	Remark       string //remark
-	Scheme       string //http https all
-	NoStore      bool
-	IsClose      bool
-	Flow         *Flow
-	Client       *Client
-	Target       *Target //目标
-	Health       `json:"-"`
-	sync.RWMutex
-}

+ 3 - 3
server/proxy/http.go

@@ -58,7 +58,7 @@ func (s *httpServer) processHttps(c net.Conn) {
 		return
 	}
 	var host *file.Host
-	file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 		v := value.(*file.Host)
 		if v.Scheme != "https" && v.Scheme != "all" {
 			return true
@@ -193,7 +193,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
 		targetAddr string
 		wg         sync.WaitGroup
 	)
-	if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
+	if host, err = file.GetDb().GetInfoByHost(r.Host, r); err != nil {
 		logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
 		goto end
 	}
@@ -245,7 +245,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
 				r.Method = "POST"
 			}
 			logs.Trace("new %s connection,clientId %d,host %s,url %s,remote address %s", r.URL.Scheme, host.Client.Id, r.Host, r.URL, r.RemoteAddr)
-			if hostTmp, err := file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
+			if hostTmp, err := file.GetDb().GetInfoByHost(r.Host, r); err != nil {
 				logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
 				break
 			} else if host != lastHost {

+ 37 - 81
server/server.go

@@ -21,27 +21,24 @@ import (
 )
 
 var (
-	Bridge       *bridge.Bridge
-	RunList      map[int]interface{} //运行中的任务
-	serverStatus []map[string]interface{}
+	Bridge  *bridge.Bridge
+	RunList map[int]interface{}
 )
 
 func init() {
 	RunList = make(map[int]interface{})
-	serverStatus = make([]map[string]interface{}, 0, 1500)
-	go getSeverStatus()
 }
 
-//从csv文件中恢复任务
+//init task from db
 func InitFromCsv() {
 	//Add a public password
 	if vkey := beego.AppConfig.String("public_vkey"); vkey != "" {
 		c := file.NewClient(vkey, true, true)
-		file.GetCsvDb().NewClient(c)
+		file.GetDb().NewClient(c)
 		RunList[c.Id] = nil
 	}
 	//Initialize services in server-side files
-	file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 		if value.(*file.Tunnel).Status {
 			AddTask(value.(*file.Tunnel))
 		}
@@ -49,6 +46,7 @@ func InitFromCsv() {
 	})
 }
 
+//get bridge command
 func DealBridgeTask() {
 	for {
 		select {
@@ -58,16 +56,16 @@ func DealBridgeTask() {
 			StopServer(t.Id)
 		case id := <-Bridge.CloseClient:
 			DelTunnelAndHostByClientId(id, true)
-			if v, ok := file.GetCsvDb().Clients.Load(id); ok {
+			if v, ok := file.GetDb().JsonDb.Clients.Load(id); ok {
 				if v.(*file.Client).NoStore {
-					file.GetCsvDb().DelClient(id)
+					file.GetDb().DelClient(id)
 				}
 			}
 		case tunnel := <-Bridge.OpenTask:
 			StartTask(tunnel.Id)
 		case s := <-Bridge.SecretChan:
 			logs.Trace("New secret connection, addr", s.Conn.Conn.RemoteAddr())
-			if t := file.GetCsvDb().GetTaskByMd5Password(s.Password); t != nil {
+			if t := file.GetDb().GetTaskByMd5Password(s.Password); t != nil {
 				if !t.Client.GetConn() {
 					logs.Info("Connections exceed the current client %d limit", t.Client.Id)
 					s.Conn.Close()
@@ -158,11 +156,11 @@ func StopServer(id int) error {
 		} else {
 			logs.Warn("stop server id %d error", id)
 		}
-		if t, err := file.GetCsvDb().GetTask(id); err != nil {
+		if t, err := file.GetDb().GetTask(id); err != nil {
 			return err
 		} else {
 			t.Status = false
-			file.GetCsvDb().UpdateTask(t)
+			file.GetDb().UpdateTask(t)
 		}
 		delete(RunList, id)
 		return nil
@@ -202,12 +200,12 @@ func AddTask(t *file.Tunnel) error {
 
 //start task
 func StartTask(id int) error {
-	if t, err := file.GetCsvDb().GetTask(id); err != nil {
+	if t, err := file.GetDb().GetTask(id); err != nil {
 		return err
 	} else {
 		AddTask(t)
 		t.Status = true
-		file.GetCsvDb().UpdateTask(t)
+		file.GetDb().UpdateTask(t)
 	}
 	return nil
 }
@@ -219,16 +217,16 @@ func DelTask(id int) error {
 			return err
 		}
 	}
-	return file.GetCsvDb().DelTask(id)
+	return file.GetDb().DelTask(id)
 }
 
 //get task list by page num
 func GetTunnel(start, length int, typeVal string, clientId int, search string) ([]*file.Tunnel, int) {
 	list := make([]*file.Tunnel, 0)
 	var cnt int
-	keys := file.GetMapKeys(file.GetCsvDb().Tasks, false, "", "")
+	keys := file.GetMapKeys(file.GetDb().JsonDb.Tasks, false, "", "")
 	for _, key := range keys {
-		if value, ok := file.GetCsvDb().Tasks.Load(key); ok {
+		if value, ok := file.GetDb().JsonDb.Tasks.Load(key); ok {
 			v := value.(*file.Tunnel)
 			if (typeVal != "" && v.Mode != typeVal || (clientId != 0 && v.Client.Id != clientId)) || (typeVal == "" && clientId != v.Client.Id) {
 				continue
@@ -257,15 +255,15 @@ func GetTunnel(start, length int, typeVal string, clientId int, search string) (
 	return list, cnt
 }
 
-//获取客户端列表
+//get client list
 func GetClientList(start, length int, search, sort, order string, clientId int) (list []*file.Client, cnt int) {
-	list, cnt = file.GetCsvDb().GetClientList(start, length, search, sort, order, clientId)
+	list, cnt = file.GetDb().GetClientList(start, length, search, sort, order, clientId)
 	dealClientData()
 	return
 }
 
 func dealClientData() {
-	file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Clients.Range(func(key, value interface{}) bool {
 		v := value.(*file.Client)
 		if _, ok := Bridge.Client.Load(v.Id); ok {
 			v.IsConnect = true
@@ -274,7 +272,7 @@ func dealClientData() {
 		}
 		v.Flow.InletFlow = 0
 		v.Flow.ExportFlow = 0
-		file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+		file.GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 			h := value.(*file.Host)
 			if h.Client.Id == v.Id {
 				v.Flow.InletFlow += h.Flow.InletFlow
@@ -282,7 +280,7 @@ func dealClientData() {
 			}
 			return true
 		})
-		file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+		file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 			t := value.(*file.Tunnel)
 			if t.Client.Id == v.Id {
 				v.Flow.InletFlow += t.Flow.InletFlow
@@ -295,10 +293,10 @@ func dealClientData() {
 	return
 }
 
-//根据客户端id删除其所属的所有隧道和域名
+//delete all host and tasks by client id
 func DelTunnelAndHostByClientId(clientId int, justDelNoStore bool) {
 	var ids []int
-	file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 		v := value.(*file.Tunnel)
 		if justDelNoStore && !v.NoStore {
 			return true
@@ -312,7 +310,7 @@ func DelTunnelAndHostByClientId(clientId int, justDelNoStore bool) {
 		DelTask(id)
 	}
 	ids = ids[:0]
-	file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Hosts.Range(func(key, value interface{}) bool {
 		v := value.(*file.Host)
 		if justDelNoStore && !v.NoStore {
 			return true
@@ -323,23 +321,23 @@ func DelTunnelAndHostByClientId(clientId int, justDelNoStore bool) {
 		return true
 	})
 	for _, id := range ids {
-		file.GetCsvDb().DelHost(id)
+		file.GetDb().DelHost(id)
 	}
 }
 
-//关闭客户端连接
+//close the client
 func DelClientConnect(clientId int) {
 	Bridge.DelClient(clientId)
 }
 
 func GetDashboardData() map[string]interface{} {
 	data := make(map[string]interface{})
-	data["hostCount"] = file.GetCsvDb().GetMapLen(file.GetCsvDb().Hosts)
-	data["clientCount"] = file.GetCsvDb().GetMapLen(file.GetCsvDb().Clients) - 1 //Remove the public key client
+	data["hostCount"] = common.GeSynctMapLen(file.GetDb().JsonDb.Hosts)
+	data["clientCount"] = common.GeSynctMapLen(file.GetDb().JsonDb.Clients) - 1 //Remove the public key client
 	dealClientData()
 	c := 0
 	var in, out int64
-	file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Clients.Range(func(key, value interface{}) bool {
 		v := value.(*file.Client)
 		if v.IsConnect {
 			c += 1
@@ -352,7 +350,7 @@ func GetDashboardData() map[string]interface{} {
 	data["inletFlowCount"] = int(in)
 	data["exportFlowCount"] = int(out)
 	var tcp, udp, secret, socks5, p2p, http int
-	file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 		switch value.(*file.Tunnel).Mode {
 		case "tcp":
 			tcp += 1
@@ -386,7 +384,7 @@ func GetDashboardData() map[string]interface{} {
 	data["logLevel"] = beego.AppConfig.String("log_level")
 	tcpCount := 0
 
-	file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Clients.Range(func(key, value interface{}) bool {
 		tcpCount += int(value.(*file.Client).NowConn)
 		return true
 	})
@@ -416,10 +414,10 @@ func GetDashboardData() map[string]interface{} {
 	}
 	//chart
 	var fg int
-	if len(serverStatus) >= 10 {
-		fg = len(serverStatus) / 10
+	if len(tool.ServerStatus) >= 10 {
+		fg = len(tool.ServerStatus) / 10
 		for i := 0; i <= 9; i++ {
-			data["sys"+strconv.Itoa(i+1)] = serverStatus[i*fg]
+			data["sys"+strconv.Itoa(i+1)] = tool.ServerStatus[i*fg]
 		}
 	}
 	return data
@@ -430,51 +428,9 @@ func flowSession(m time.Duration) {
 	for {
 		select {
 		case <-ticker.C:
-			file.GetCsvDb().StoreHostToCsv()
-			file.GetCsvDb().StoreTasksToCsv()
+			file.GetDb().JsonDb.StoreHostToJsonFile()
+			file.GetDb().JsonDb.StoreTasksToJsonFile()
+			file.GetDb().JsonDb.StoreClientsToJsonFile()
 		}
 	}
 }
-
-func getSeverStatus() {
-	for {
-		if len(serverStatus) < 10 {
-			time.Sleep(time.Second)
-		} else {
-			time.Sleep(time.Minute)
-		}
-		cpuPercet, _ := cpu.Percent(0, true)
-		var cpuAll float64
-		for _, v := range cpuPercet {
-			cpuAll += v
-		}
-		m := make(map[string]interface{})
-		loads, _ := load.Avg()
-		m["load1"] = loads.Load1
-		m["load5"] = loads.Load5
-		m["load15"] = loads.Load15
-		m["cpu"] = math.Round(cpuAll / float64(len(cpuPercet)))
-		swap, _ := mem.SwapMemory()
-		m["swap_mem"] = math.Round(swap.UsedPercent)
-		vir, _ := mem.VirtualMemory()
-		m["virtual_mem"] = math.Round(vir.UsedPercent)
-		conn, _ := net.ProtoCounters(nil)
-		io1, _ := net.IOCounters(false)
-		time.Sleep(time.Millisecond * 500)
-		io2, _ := net.IOCounters(false)
-		if len(io2) > 0 && len(io1) > 0 {
-			m["io_send"] = (io2[0].BytesSent - io1[0].BytesSent) * 2
-			m["io_recv"] = (io2[0].BytesRecv - io1[0].BytesRecv) * 2
-		}
-		t := time.Now()
-		m["time"] = strconv.Itoa(t.Hour()) + ":" + strconv.Itoa(t.Minute()) + ":" + strconv.Itoa(t.Second())
-
-		for _, v := range conn {
-			m[v.Protocol] = v.Stats["CurrEstab"]
-		}
-		if len(serverStatus) >= 1440 {
-			serverStatus = serverStatus[1:]
-		}
-		serverStatus = append(serverStatus, m)
-	}
-}

+ 1 - 1
server/test/test.go

@@ -12,7 +12,7 @@ import (
 func TestServerConfig() {
 	var postTcpArr []int
 	var postUdpArr []int
-	file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
+	file.GetDb().JsonDb.Tasks.Range(func(key, value interface{}) bool {
 		v := value.(*file.Tunnel)
 		if v.Mode == "udp" {
 			isInArr(&postUdpArr, v.Port, v.Remark, "udp")

+ 61 - 1
server/tool/utils.go

@@ -3,9 +3,24 @@ package tool
 import (
 	"github.com/cnlh/nps/lib/common"
 	"github.com/cnlh/nps/vender/github.com/astaxie/beego"
+	"github.com/shirou/gopsutil/cpu"
+	"github.com/shirou/gopsutil/load"
+	"github.com/shirou/gopsutil/mem"
+	"github.com/shirou/gopsutil/net"
+	"math"
+	"strconv"
+	"time"
 )
 
-var ports []int
+var (
+	ports        []int
+	ServerStatus []map[string]interface{}
+)
+
+func init() {
+	ServerStatus = make([]map[string]interface{}, 0, 1500)
+	go getSeverStatus()
+}
 
 func InitAllowPort() {
 	p := beego.AppConfig.String("allow_ports")
@@ -28,3 +43,48 @@ func TestServerPort(p int, m string) (b bool) {
 	}
 	return
 }
+
+func getSeverStatus() {
+	for {
+		if len(ServerStatus) < 10 {
+			time.Sleep(time.Second)
+		} else {
+			time.Sleep(time.Minute)
+		}
+		cpuPercet, _ := cpu.Percent(0, true)
+		var cpuAll float64
+		for _, v := range cpuPercet {
+			cpuAll += v
+		}
+		m := make(map[string]interface{})
+		loads, _ := load.Avg()
+		m["load1"] = loads.Load1
+		m["load5"] = loads.Load5
+		m["load15"] = loads.Load15
+		m["cpu"] = math.Round(cpuAll / float64(len(cpuPercet)))
+		swap, _ := mem.SwapMemory()
+		m["swap_mem"] = math.Round(swap.UsedPercent)
+		vir, _ := mem.VirtualMemory()
+		m["virtual_mem"] = math.Round(vir.UsedPercent)
+		conn, _ := net.ProtoCounters(nil)
+		io1, _ := net.IOCounters(false)
+		time.Sleep(time.Millisecond * 500)
+		io2, _ := net.IOCounters(false)
+		if len(io2) > 0 && len(io1) > 0 {
+			m["io_send"] = (io2[0].BytesSent - io1[0].BytesSent) * 2
+			m["io_recv"] = (io2[0].BytesRecv - io1[0].BytesRecv) * 2
+		}
+		t := time.Now()
+		m["time"] = strconv.Itoa(t.Hour()) + ":" + strconv.Itoa(t.Minute()) + ":" + strconv.Itoa(t.Second())
+
+		for _, v := range conn {
+			m[v.Protocol] = v.Stats["CurrEstab"]
+		}
+		if len(ServerStatus) >= 1440 {
+			ServerStatus = ServerStatus[1:]
+		}
+		ServerStatus = append(ServerStatus, m)
+	}
+}
+
+

+ 2 - 2
web/controllers/base.go

@@ -156,13 +156,13 @@ func (s *BaseController) CheckUserAuth() {
 		if id := s.GetIntNoErr("id"); id != 0 {
 			belong := false
 			if strings.Contains(s.actionName, "h") {
-				if v, ok := file.GetCsvDb().Hosts.Load(id); ok {
+				if v, ok := file.GetDb().JsonDb.Hosts.Load(id); ok {
 					if v.(*file.Host).Client.Id == s.GetSession("clientId").(int) {
 						belong = true
 					}
 				}
 			} else {
-				if v, ok := file.GetCsvDb().Tasks.Load(id); ok {
+				if v, ok := file.GetDb().JsonDb.Tasks.Load(id); ok {
 					if v.(*file.Tunnel).Client.Id == s.GetSession("clientId").(int) {
 						belong = true
 					}

+ 10 - 10
web/controllers/client.go

@@ -40,7 +40,7 @@ func (s *ClientController) Add() {
 	} else {
 		t := &file.Client{
 			VerifyKey: s.GetString("vkey"),
-			Id:        int(file.GetCsvDb().GetClientId()),
+			Id:        int(file.GetDb().JsonDb.GetClientId()),
 			Status:    true,
 			Remark:    s.GetString("remark"),
 			Cnf: &file.Config{
@@ -64,7 +64,7 @@ func (s *ClientController) Add() {
 			t.Rate = rate.NewRate(int64(t.RateLimit * 1024))
 			t.Rate.Start()
 		}
-		if err := file.GetCsvDb().NewClient(t); err != nil {
+		if err := file.GetDb().NewClient(t); err != nil {
 			s.AjaxErr(err.Error())
 		}
 		s.AjaxOk("add success")
@@ -74,7 +74,7 @@ func (s *ClientController) GetClient() {
 	if s.Ctx.Request.Method == "POST" {
 		id := s.GetIntNoErr("id")
 		data := make(map[string]interface{})
-		if c, err := file.GetCsvDb().GetClient(id); err != nil {
+		if c, err := file.GetDb().GetClient(id); err != nil {
 			data["code"] = 0
 		} else {
 			data["code"] = 1
@@ -90,7 +90,7 @@ func (s *ClientController) Edit() {
 	id := s.GetIntNoErr("id")
 	if s.Ctx.Request.Method == "GET" {
 		s.Data["menu"] = "client"
-		if c, err := file.GetCsvDb().GetClient(id); err != nil {
+		if c, err := file.GetDb().GetClient(id); err != nil {
 			s.error()
 		} else {
 			s.Data["c"] = c
@@ -98,17 +98,17 @@ func (s *ClientController) Edit() {
 		s.SetInfo("edit client")
 		s.display()
 	} else {
-		if c, err := file.GetCsvDb().GetClient(id); err != nil {
+		if c, err := file.GetDb().GetClient(id); err != nil {
 			s.error()
 		} else {
 			if s.GetString("web_username") != "" {
-				if s.GetString("web_username") == beego.AppConfig.String("web_username") || !file.GetCsvDb().VerifyUserName(s.GetString("web_username"), c.Id) {
+				if s.GetString("web_username") == beego.AppConfig.String("web_username") || !file.GetDb().VerifyUserName(s.GetString("web_username"), c.Id) {
 					s.AjaxErr("web login username duplicate, please reset")
 					return
 				}
 			}
 			if s.GetSession("isAdmin").(bool) {
-				if !file.GetCsvDb().VerifyVkey(s.GetString("vkey"), c.Id) {
+				if !file.GetDb().VerifyVkey(s.GetString("vkey"), c.Id) {
 					s.AjaxErr("Vkey duplicate, please reset")
 					return
 				}
@@ -135,7 +135,7 @@ func (s *ClientController) Edit() {
 				c.Rate = rate.NewRate(int64(2 << 23))
 				c.Rate.Start()
 			}
-			file.GetCsvDb().StoreClientsToCsv()
+			file.GetDb().JsonDb.StoreClientsToJsonFile()
 		}
 		s.AjaxOk("save success")
 	}
@@ -144,7 +144,7 @@ func (s *ClientController) Edit() {
 //更改状态
 func (s *ClientController) ChangeStatus() {
 	id := s.GetIntNoErr("id")
-	if client, err := file.GetCsvDb().GetClient(id); err == nil {
+	if client, err := file.GetDb().GetClient(id); err == nil {
 		client.Status = s.GetBoolNoErr("status")
 		if client.Status == false {
 			server.DelClientConnect(client.Id)
@@ -157,7 +157,7 @@ func (s *ClientController) ChangeStatus() {
 //删除客户端
 func (s *ClientController) Del() {
 	id := s.GetIntNoErr("id")
-	if err := file.GetCsvDb().DelClient(id); err != nil {
+	if err := file.GetDb().DelClient(id); err != nil {
 		s.AjaxErr("delete error")
 	}
 	server.DelTunnelAndHostByClientId(id, false)

+ 19 - 19
web/controllers/index.go

@@ -94,7 +94,7 @@ func (s *IndexController) Add() {
 			ServerIp:  s.GetString("server_ip"),
 			Mode:      s.GetString("type"),
 			Target:    &file.Target{TargetStr: s.GetString("target")},
-			Id:        int(file.GetCsvDb().GetTaskId()),
+			Id:        int(file.GetDb().JsonDb.GetTaskId()),
 			Status:    true,
 			Remark:    s.GetString("remark"),
 			Password:  s.GetString("password"),
@@ -106,10 +106,10 @@ func (s *IndexController) Add() {
 			s.AjaxErr("The port cannot be opened because it may has been occupied or is no longer allowed.")
 		}
 		var err error
-		if t.Client, err = file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
+		if t.Client, err = file.GetDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
 			s.AjaxErr(err.Error())
 		}
-		if err := file.GetCsvDb().NewTask(t); err != nil {
+		if err := file.GetDb().NewTask(t); err != nil {
 			s.AjaxErr(err.Error())
 		}
 		if err := server.AddTask(t); err != nil {
@@ -122,7 +122,7 @@ func (s *IndexController) Add() {
 func (s *IndexController) GetOneTunnel() {
 	id := s.GetIntNoErr("id")
 	data := make(map[string]interface{})
-	if t, err := file.GetCsvDb().GetTask(id); err != nil {
+	if t, err := file.GetDb().GetTask(id); err != nil {
 		data["code"] = 0
 	} else {
 		data["code"] = 1
@@ -134,7 +134,7 @@ func (s *IndexController) GetOneTunnel() {
 func (s *IndexController) Edit() {
 	id := s.GetIntNoErr("id")
 	if s.Ctx.Request.Method == "GET" {
-		if t, err := file.GetCsvDb().GetTask(id); err != nil {
+		if t, err := file.GetDb().GetTask(id); err != nil {
 			s.error()
 		} else {
 			s.Data["t"] = t
@@ -142,10 +142,10 @@ func (s *IndexController) Edit() {
 		s.SetInfo("edit tunnel")
 		s.display()
 	} else {
-		if t, err := file.GetCsvDb().GetTask(id); err != nil {
+		if t, err := file.GetDb().GetTask(id); err != nil {
 			s.error()
 		} else {
-			if client, err := file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
+			if client, err := file.GetDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
 				s.AjaxErr("modified error,the client is not exist")
 				return
 			} else {
@@ -166,7 +166,7 @@ func (s *IndexController) Edit() {
 			t.LocalPath = s.GetString("local_path")
 			t.StripPre = s.GetString("strip_pre")
 			t.Remark = s.GetString("remark")
-			file.GetCsvDb().UpdateTask(t)
+			file.GetDb().UpdateTask(t)
 			server.StopServer(t.Id)
 			server.StartTask(t.Id)
 		}
@@ -207,7 +207,7 @@ func (s *IndexController) HostList() {
 	} else {
 		start, length := s.GetAjaxParams()
 		clientId := s.GetIntNoErr("client_id")
-		list, cnt := file.GetCsvDb().GetHost(start, length, clientId, s.GetString("search"))
+		list, cnt := file.GetDb().GetHost(start, length, clientId, s.GetString("search"))
 		s.AjaxTable(list, cnt, cnt)
 	}
 }
@@ -215,7 +215,7 @@ func (s *IndexController) HostList() {
 func (s *IndexController) GetHost() {
 	if s.Ctx.Request.Method == "POST" {
 		data := make(map[string]interface{})
-		if h, err := file.GetCsvDb().GetHostById(s.GetIntNoErr("id")); err != nil {
+		if h, err := file.GetDb().GetHostById(s.GetIntNoErr("id")); err != nil {
 			data["code"] = 0
 		} else {
 			data["data"] = h
@@ -228,7 +228,7 @@ func (s *IndexController) GetHost() {
 
 func (s *IndexController) DelHost() {
 	id := s.GetIntNoErr("id")
-	if err := file.GetCsvDb().DelHost(id); err != nil {
+	if err := file.GetDb().DelHost(id); err != nil {
 		s.AjaxErr("delete error")
 	}
 	s.AjaxOk("delete success")
@@ -242,7 +242,7 @@ func (s *IndexController) AddHost() {
 		s.display("index/hadd")
 	} else {
 		h := &file.Host{
-			Id:           int(file.GetCsvDb().GetHostId()),
+			Id:           int(file.GetDb().JsonDb.GetHostId()),
 			Host:         s.GetString("host"),
 			Target:       &file.Target{TargetStr: s.GetString("target")},
 			HeaderChange: s.GetString("header"),
@@ -253,10 +253,10 @@ func (s *IndexController) AddHost() {
 			Scheme:       s.GetString("scheme"),
 		}
 		var err error
-		if h.Client, err = file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
+		if h.Client, err = file.GetDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
 			s.AjaxErr("add error")
 		}
-		if err := file.GetCsvDb().NewHost(h); err != nil {
+		if err := file.GetDb().NewHost(h); err != nil {
 			s.AjaxErr("add fail" + err.Error())
 		}
 		s.AjaxOk("add success")
@@ -267,7 +267,7 @@ func (s *IndexController) EditHost() {
 	id := s.GetIntNoErr("id")
 	if s.Ctx.Request.Method == "GET" {
 		s.Data["menu"] = "host"
-		if h, err := file.GetCsvDb().GetHostById(id); err != nil {
+		if h, err := file.GetDb().GetHostById(id); err != nil {
 			s.error()
 		} else {
 			s.Data["h"] = h
@@ -275,7 +275,7 @@ func (s *IndexController) EditHost() {
 		s.SetInfo("edit")
 		s.display("index/hedit")
 	} else {
-		if h, err := file.GetCsvDb().GetHostById(id); err != nil {
+		if h, err := file.GetDb().GetHostById(id); err != nil {
 			s.error()
 		} else {
 			if h.Host != s.GetString("host") {
@@ -283,12 +283,12 @@ func (s *IndexController) EditHost() {
 				tmpHost.Host = s.GetString("host")
 				tmpHost.Location = s.GetString("location")
 				tmpHost.Scheme = s.GetString("scheme")
-				if file.GetCsvDb().IsHostExist(tmpHost) {
+				if file.GetDb().IsHostExist(tmpHost) {
 					s.AjaxErr("host has exist")
 					return
 				}
 			}
-			if client, err := file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
+			if client, err := file.GetDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
 				s.AjaxErr("modified error,the client is not exist")
 			} else {
 				h.Client = client
@@ -300,7 +300,7 @@ func (s *IndexController) EditHost() {
 			h.Remark = s.GetString("remark")
 			h.Location = s.GetString("location")
 			h.Scheme = s.GetString("scheme")
-			file.GetCsvDb().StoreHostToCsv()
+			file.GetDb().JsonDb.StoreHostToJsonFile()
 		}
 		s.AjaxOk("modified success")
 	}

+ 1 - 1
web/controllers/login.go

@@ -24,7 +24,7 @@ func (self *LoginController) Verify() {
 	}
 	b, err := beego.AppConfig.Bool("allow_user_login")
 	if err == nil && b && !auth {
-		file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
+		file.GetDb().JsonDb.Clients.Range(func(key, value interface{}) bool {
 			v := value.(*file.Client)
 			if !v.Status || v.NoDisplay {
 				return true