Db file change

This commit is contained in:
刘河 2019-03-29 15:21:30 +08:00
parent cd7f99063c
commit 5fd335f330
17 changed files with 597 additions and 567 deletions

View File

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

View File

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

View File

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

View File

@ -210,21 +210,6 @@ func (s *Conn) SendHostInfo(h *file.Host) (int, error) {
return s.Write(raw.Bytes()) 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 //get task info
func (s *Conn) GetHostInfo() (h *file.Host, err error) { func (s *Conn) GetHostInfo() (h *file.Host, err error) {
var l int 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) arr := strings.Split(string(buf[:l]), common.CONN_DATA_SEQ)
h = new(file.Host) h = new(file.Host)
h.Target = new(file.Target) h.Target = new(file.Target)
h.Id = int(file.GetCsvDb().GetHostId()) h.Id = int(file.GetDb().JsonDb.GetHostId())
h.Host = arr[0] h.Host = arr[0]
h.Target.TargetStr = arr[1] h.Target.TargetStr = arr[1]
h.HeaderChange = arr[2] h.HeaderChange = arr[2]
@ -328,7 +313,7 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
t.Mode = arr[0] t.Mode = arr[0]
t.Ports = arr[1] t.Ports = arr[1]
t.Target.TargetStr = arr[2] t.Target.TargetStr = arr[2]
t.Id = int(file.GetCsvDb().GetTaskId()) t.Id = int(file.GetDb().JsonDb.GetTaskId())
t.Status = true t.Status = true
t.Flow = new(file.Flow) t.Flow = new(file.Flow)
t.Remark = arr[3] t.Remark = arr[3]
@ -379,6 +364,21 @@ func (s *Conn) WriteChan() (int, error) {
return s.Write([]byte(common.WORK_CHAN)) 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) //get the assembled amount data(len 4 and content)
func GetLenBytes(buf []byte) (b []byte, err error) { func GetLenBytes(buf []byte) (b []byte, err error) {
raw := bytes.NewBuffer([]byte{}) raw := bytes.NewBuffer([]byte{})

View File

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

View File

@ -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
lib/file/db.go Normal file
View File

@ -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
}

View File

@ -3,21 +3,17 @@ package file
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"github.com/cnlh/nps/lib/common" "github.com/cnlh/nps/lib/common"
"github.com/cnlh/nps/lib/crypt"
"github.com/cnlh/nps/lib/rate" "github.com/cnlh/nps/lib/rate"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
) )
func NewCsv(runPath string) *Csv { func NewJsonDb(runPath string) *JsonDb {
return &Csv{ return &JsonDb{
RunPath: runPath, RunPath: runPath,
TaskFilePath: filepath.Join(runPath, "conf", "tasks.json"), TaskFilePath: filepath.Join(runPath, "conf", "tasks.json"),
HostFilePath: filepath.Join(runPath, "conf", "hosts.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 Tasks sync.Map
Hosts sync.Map //域名列表 Hosts sync.Map
HostsTmp sync.Map HostsTmp sync.Map
Clients sync.Map //客户端 Clients sync.Map
RunPath string //存储根目录 RunPath string
ClientIncreaseId int32 //客户端id ClientIncreaseId int32 //client increased id
TaskIncreaseId int32 //任务自增ID TaskIncreaseId int32 //task increased id
HostIncreaseId int32 //host increased id HostIncreaseId int32 //host increased id
TaskFilePath string TaskFilePath string //task file path
HostFilePath string HostFilePath string //host file path
ClientFilePath string ClientFilePath string //client file path
} }
func (s *Csv) LoadTaskFromCsv() { func (s *JsonDb) LoadTaskFromJsonFile() {
loadSyncMapFromFile(s.TaskFilePath, func(v string) { loadSyncMapFromFile(s.TaskFilePath, func(v string) {
var err error var err error
post := new(Tunnel) 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) { loadSyncMapFromFile(s.ClientFilePath, func(v string) {
post := new(Client) post := new(Client)
if json.Unmarshal([]byte(v), &post) != nil { if json.Unmarshal([]byte(v), &post) != nil {
@ -68,6 +64,7 @@ func (s *Csv) LoadClientFromCsv() {
post.Rate = rate.NewRate(int64(2 << 23)) post.Rate = rate.NewRate(int64(2 << 23))
} }
post.Rate.Start() post.Rate.Start()
post.NowConn = 0
s.Clients.Store(post.Id, post) s.Clients.Store(post.Id, post)
if post.Id > int(s.ClientIncreaseId) { if post.Id > int(s.ClientIncreaseId) {
s.ClientIncreaseId = int32(post.Id) 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) { loadSyncMapFromFile(s.HostFilePath, func(v string) {
var err error var err error
post := new(Host) post := new(Host)
@ -92,259 +89,7 @@ func (s *Csv) LoadHostFromCsv() {
}) })
} }
func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (id int, err error) { func (s *JsonDb) GetClient(id int) (c *Client, 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) {
if v, ok := s.Clients.Load(id); ok { if v, ok := s.Clients.Load(id); ok {
c = v.(*Client) c = v.(*Client)
return return
@ -353,84 +98,27 @@ func (s *Csv) GetClient(id int) (c *Client, err error) {
return return
} }
func (s *Csv) GetClientIdByVkey(vkey string) (id int, err error) { func (s *JsonDb) StoreHostToJsonFile() {
var exist bool storeSyncMapToFile(s.Hosts, s.HostFilePath)
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 *Csv) GetHostById(id int) (h *Host, err error) { func (s *JsonDb) StoreTasksToJsonFile() {
if v, ok := s.Hosts.Load(id); ok { storeSyncMapToFile(s.Tasks, s.TaskFilePath)
h = v.(*Host)
return
}
err = errors.New("The host could not be parsed")
return
} }
//get key by host from x func (s *JsonDb) StoreClientsToJsonFile() {
func (s *Csv) GetInfoByHost(host string, r *http.Request) (h *Host, err error) { storeSyncMapToFile(s.Clients, s.ClientFilePath)
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 *Csv) GetClientId() int32 { func (s *JsonDb) GetClientId() int32 {
return atomic.AddInt32(&s.ClientIncreaseId, 1) return atomic.AddInt32(&s.ClientIncreaseId, 1)
} }
func (s *Csv) GetTaskId() int32 { func (s *JsonDb) GetTaskId() int32 {
return atomic.AddInt32(&s.TaskIncreaseId, 1) return atomic.AddInt32(&s.TaskIncreaseId, 1)
} }
func (s *Csv) GetHostId() int32 { func (s *JsonDb) GetHostId() int32 {
return atomic.AddInt32(&s.HostIncreaseId, 1) return atomic.AddInt32(&s.HostIncreaseId, 1)
} }

View File

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

View File

@ -58,7 +58,7 @@ func (s *httpServer) processHttps(c net.Conn) {
return return
} }
var host *file.Host 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) v := value.(*file.Host)
if v.Scheme != "https" && v.Scheme != "all" { if v.Scheme != "https" && v.Scheme != "all" {
return true return true
@ -193,7 +193,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
targetAddr string targetAddr string
wg sync.WaitGroup 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) logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
goto end goto end
} }
@ -245,7 +245,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
r.Method = "POST" 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) 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) logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
break break
} else if host != lastHost { } else if host != lastHost {

View File

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

View File

@ -12,7 +12,7 @@ import (
func TestServerConfig() { func TestServerConfig() {
var postTcpArr []int var postTcpArr []int
var postUdpArr []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) v := value.(*file.Tunnel)
if v.Mode == "udp" { if v.Mode == "udp" {
isInArr(&postUdpArr, v.Port, v.Remark, "udp") isInArr(&postUdpArr, v.Port, v.Remark, "udp")

View File

@ -3,9 +3,24 @@ package tool
import ( import (
"github.com/cnlh/nps/lib/common" "github.com/cnlh/nps/lib/common"
"github.com/cnlh/nps/vender/github.com/astaxie/beego" "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() { func InitAllowPort() {
p := beego.AppConfig.String("allow_ports") p := beego.AppConfig.String("allow_ports")
@ -28,3 +43,48 @@ func TestServerPort(p int, m string) (b bool) {
} }
return 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)
}
}

View File

@ -156,13 +156,13 @@ func (s *BaseController) CheckUserAuth() {
if id := s.GetIntNoErr("id"); id != 0 { if id := s.GetIntNoErr("id"); id != 0 {
belong := false belong := false
if strings.Contains(s.actionName, "h") { 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) { if v.(*file.Host).Client.Id == s.GetSession("clientId").(int) {
belong = true belong = true
} }
} }
} else { } 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) { if v.(*file.Tunnel).Client.Id == s.GetSession("clientId").(int) {
belong = true belong = true
} }

View File

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

View File

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

View File

@ -24,7 +24,7 @@ func (self *LoginController) Verify() {
} }
b, err := beego.AppConfig.Bool("allow_user_login") b, err := beego.AppConfig.Bool("allow_user_login")
if err == nil && b && !auth { 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) v := value.(*file.Client)
if !v.Status || v.NoDisplay { if !v.Status || v.NoDisplay {
return true return true