nps/utils/file.go

495 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package utils
import (
"easyProxy/utils"
"encoding/csv"
"errors"
"github.com/astaxie/beego"
"log"
"os"
"strconv"
"strings"
"sync"
)
var (
CsvDb *Csv
once sync.Once
)
type Flow struct {
ExportFlow int64 //出口流量
InletFlow int64 //入口流量
FlowLimit int64 //流量限制,出口+入口 /M
}
type Client struct {
Cnf *Config
Id int //id
VerifyKey string //验证密钥
Addr string //客户端ip地址
Remark string //备注
Status bool //是否开启
IsConnect bool //是否连接
RateLimit int //速度限制 /kb
Flow *Flow //流量
Rate *Rate //速度控制
}
type Tunnel struct {
Id int //Id
TcpPort int //服务端与客户端通信端口
Mode string //启动方式
Target string //目标
Status bool //是否开启
Client *Client //所属客户端id
Flow *Flow
Config *Config
UseClientCnf bool //是否继承客户端配置
Remark string //备注
}
type Config struct {
U string //socks5验证用户名
P string //socks5验证密码
Compress string //压缩方式
Crypt bool //是否加密
Mux bool //是否加密
CompressEncode int //加密方式
CompressDecode int //解密方式
}
type Host struct {
Host string //启动方式
Target string //目标
HeaderChange string //host修改
HostChange string //host修改
Flow *Flow
Client *Client
Remark string //备注
}
func NewCsv() *Csv {
c := new(Csv)
return c
}
type Csv struct {
Tasks []*Tunnel
Path string
Hosts []*Host //域名列表
Clients []*Client //客户端
ClientIncreaseId int //客户端id
TaskIncreaseId int //任务自增ID
sync.Mutex
}
func (s *Csv) Init() {
s.LoadClientFromCsv()
s.LoadTaskFromCsv()
s.LoadHostFromCsv()
}
func (s *Csv) StoreTasksToCsv() {
// 创建文件
csvFile, err := os.Create(beego.AppPath + "/conf/tasks.csv")
if err != nil {
log.Fatalf(err.Error())
}
defer csvFile.Close()
writer := csv.NewWriter(csvFile)
for _, task := range s.Tasks {
record := []string{
strconv.Itoa(task.TcpPort),
task.Mode,
task.Target,
task.Config.U,
task.Config.P,
task.Config.Compress,
utils.GetStrByBool(task.Status),
GetStrByBool(task.Config.Crypt),
GetStrByBool(task.Config.Mux),
strconv.Itoa(task.Config.CompressEncode),
strconv.Itoa(task.Config.CompressDecode),
strconv.Itoa(task.Id),
strconv.Itoa(task.Client.Id),
strconv.FormatBool(task.UseClientCnf),
task.Remark,
}
err := writer.Write(record)
if err != nil {
log.Fatalf(err.Error())
}
}
writer.Flush()
}
func (s *Csv) openFile(path string) ([][]string, error) {
// 打开文件
file, err := os.Open(path)
if err != nil {
panic(err)
}
defer file.Close()
// 获取csv的reader
reader := csv.NewReader(file)
// 设置FieldsPerRecord为-1
reader.FieldsPerRecord = -1
// 读取文件中所有行保存到slice中
return reader.ReadAll()
}
func (s *Csv) LoadTaskFromCsv() {
path := beego.AppPath + "/conf/tasks.csv"
records, err := s.openFile(path)
if err != nil {
log.Fatal("配置文件打开错误:", path)
}
var tasks []*Tunnel
// 将每一行数据保存到内存slice中
for _, item := range records {
post := &Tunnel{
TcpPort: GetIntNoErrByStr(item[0]),
Mode: item[1],
Target: item[2],
Config: &Config{
U: item[3],
P: item[4],
Compress: item[5],
Crypt: GetBoolByStr(item[7]),
Mux: GetBoolByStr(item[8]),
CompressEncode: GetIntNoErrByStr(item[9]),
CompressDecode: GetIntNoErrByStr(item[10]),
},
Status: utils.GetBoolByStr(item[6]),
Id: GetIntNoErrByStr(item[11]),
UseClientCnf: GetBoolByStr(item[13]),
Remark: item[14],
}
post.Flow = new(Flow)
if post.Client, err = s.GetClient(GetIntNoErrByStr(item[12])); err != nil {
continue
}
tasks = append(tasks, post)
if post.Id > s.TaskIncreaseId {
s.TaskIncreaseId = post.Id
}
}
s.Tasks = tasks
}
func (s *Csv) GetTaskId() int {
s.Lock()
defer s.Unlock()
s.TaskIncreaseId++
return s.TaskIncreaseId
}
func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (int, error) {
s.Lock()
defer s.Unlock()
for _, v := range s.Clients {
if utils.Getverifyval(v.VerifyKey) == vKey && v.Status {
if arr := strings.Split(addr, ":"); len(arr) > 0 {
v.Addr = arr[0]
}
return v.Id, nil
}
}
return 0, errors.New("not found")
}
func (s *Csv) NewTask(t *Tunnel) {
t.Flow = new(Flow)
s.Tasks = append(s.Tasks, t)
s.StoreTasksToCsv()
}
func (s *Csv) UpdateTask(t *Tunnel) error {
for k, v := range s.Tasks {
if v.Id == t.Id {
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
s.Tasks = append(s.Tasks, t)
s.StoreTasksToCsv()
return nil
}
}
return errors.New("不存在")
}
func (s *Csv) DelTask(id int) error {
for k, v := range s.Tasks {
if v.Id == id {
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
s.StoreTasksToCsv()
return nil
}
}
return errors.New("不存在")
}
func (s *Csv) GetTask(id int) (v *Tunnel, err error) {
for _, v = range s.Tasks {
if v.Id == id {
return
}
}
err = errors.New("未找到")
return
}
func (s *Csv) StoreHostToCsv() {
// 创建文件
csvFile, err := os.Create(beego.AppPath + "/conf/hosts.csv")
if err != nil {
panic(err)
}
defer csvFile.Close()
// 获取csv的Writer
writer := csv.NewWriter(csvFile)
// 将map中的Post转换成slice因为csv的Write需要slice参数
// 并写入csv文件
for _, host := range s.Hosts {
record := []string{
host.Host,
host.Target,
strconv.Itoa(host.Client.Id),
host.HeaderChange,
host.HostChange,
host.Remark,
}
err1 := writer.Write(record)
if err1 != nil {
panic(err1)
}
}
// 确保所有内存数据刷到csv文件
writer.Flush()
}
func (s *Csv) LoadClientFromCsv() {
path := beego.AppPath + "/conf/clients.csv"
records, err := s.openFile(path)
if err != nil {
log.Fatal("配置文件打开错误:", path)
}
var clients []*Client
// 将每一行数据保存到内存slice中
for _, item := range records {
post := &Client{
Id: GetIntNoErrByStr(item[0]),
VerifyKey: item[1],
Remark: item[2],
Status: GetBoolByStr(item[3]),
RateLimit: GetIntNoErrByStr(item[9]),
Cnf: &Config{
U: item[4],
P: item[5],
Crypt: GetBoolByStr(item[6]),
Mux: GetBoolByStr(item[7]),
Compress: item[8],
},
}
if post.Id > s.ClientIncreaseId {
s.ClientIncreaseId = post.Id
}
if post.RateLimit > 0 {
post.Rate = NewRate(int64(post.RateLimit * 1024))
post.Rate.Start()
}
post.Flow = new(Flow)
post.Flow.FlowLimit = int64(utils.GetIntNoerrByStr(item[10]))
clients = append(clients, post)
}
s.Clients = clients
}
func (s *Csv) LoadHostFromCsv() {
path := beego.AppPath + "/conf/hosts.csv"
records, err := s.openFile(path)
if err != nil {
log.Fatal("配置文件打开错误:", path)
}
var hosts []*Host
// 将每一行数据保存到内存slice中
for _, item := range records {
post := &Host{
Host: item[0],
Target: item[1],
HeaderChange: item[3],
HostChange: item[4],
Remark: item[5],
}
if post.Client, err = s.GetClient(GetIntNoErrByStr(item[2])); err != nil {
continue
}
post.Flow = new(Flow)
hosts = append(hosts, post)
}
s.Hosts = hosts
}
func (s *Csv) DelHost(host string) error {
for k, v := range s.Hosts {
if v.Host == host {
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
s.StoreHostToCsv()
return nil
}
}
return errors.New("不存在")
}
func (s *Csv) NewHost(t *Host) {
t.Flow = new(Flow)
s.Hosts = append(s.Hosts, t)
s.StoreHostToCsv()
}
func (s *Csv) UpdateHost(t *Host) error {
for k, v := range s.Hosts {
if v.Host == t.Host {
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
s.Hosts = append(s.Hosts, t)
s.StoreHostToCsv()
return nil
}
}
return errors.New("不存在")
}
func (s *Csv) GetHost(start, length int, id int) ([]*Host, int) {
list := make([]*Host, 0)
var cnt int
for _, v := range s.Hosts {
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 {
for k, v := range s.Clients {
if v.Id == id {
s.Clients = append(s.Clients[:k], s.Clients[k+1:]...)
s.StoreClientsToCsv()
return nil
}
}
return errors.New("不存在")
}
func (s *Csv) NewClient(c *Client) {
s.Lock()
defer s.Unlock()
c.Flow = new(Flow)
s.Clients = append(s.Clients, c)
s.StoreClientsToCsv()
}
func (s *Csv) GetClientId() int {
s.Lock()
defer s.Unlock()
s.ClientIncreaseId++
return s.ClientIncreaseId
}
func (s *Csv) UpdateClient(t *Client) error {
s.Lock()
defer s.Unlock()
for k, v := range s.Clients {
if v.Id == t.Id {
s.Clients = append(s.Clients[:k], s.Clients[k+1:]...)
s.Clients = append(s.Clients, t)
s.StoreClientsToCsv()
return nil
}
}
return errors.New("不存在")
}
func (s *Csv) GetClientList(start, length int) ([]*Client, int) {
list := make([]*Client, 0)
var cnt int
for _, v := range s.Clients {
cnt++
if start--; start < 0 {
if length--; length > 0 {
list = append(list, v)
}
}
}
return list, cnt
}
func (s *Csv) GetClient(id int) (v *Client, err error) {
for _, v = range s.Clients {
if v.Id == id {
return
}
}
err = errors.New("未找到")
return
}
func (s *Csv) StoreClientsToCsv() {
// 创建文件
csvFile, err := os.Create(beego.AppPath + "/conf/clients.csv")
if err != nil {
log.Fatalf(err.Error())
}
defer csvFile.Close()
writer := csv.NewWriter(csvFile)
for _, client := range s.Clients {
record := []string{
strconv.Itoa(client.Id),
client.VerifyKey,
client.Remark,
strconv.FormatBool(client.Status),
client.Cnf.U,
client.Cnf.P,
utils.GetStrByBool(client.Cnf.Crypt),
utils.GetStrByBool(client.Cnf.Mux),
client.Cnf.Compress,
strconv.Itoa(client.RateLimit),
strconv.Itoa(int(client.Flow.FlowLimit)),
}
err := writer.Write(record)
if err != nil {
log.Fatalf(err.Error())
}
}
writer.Flush()
}
//init csv from file
func GetCsvDb() *Csv {
once.Do(func() {
CsvDb = NewCsv()
CsvDb.Init()
})
return CsvDb
}
//深拷贝Tunnel
func DeepCopyConfig(c *Config) *Config {
return &Config{
U: c.U,
P: c.P,
Compress: c.Compress,
Crypt: c.Crypt,
Mux: c.Mux,
CompressEncode: c.CompressEncode,
CompressDecode: c.CompressDecode,
}
}