package file import ( "github.com/cnlh/nps/lib/rate" "github.com/pkg/errors" "strings" "sync" "sync/atomic" "time" ) type Flow struct { ExportFlow int64 InletFlow int64 FlowLimit int64 sync.RWMutex } func (s *Flow) Add(in, out int64) { s.Lock() defer s.Unlock() s.InletFlow += int64(in) s.ExportFlow += int64(out) } type Client struct { Cnf *Config Id int //id VerifyKey string //verify key Addr string //the ip of client Remark string //remark Status bool //is allow connect IsConnect bool //is the client connect RateLimit int //rate /kb Flow *Flow //flow setting Rate *rate.Rate //rate limit NoStore bool //no store to file NoDisplay bool //no display on web MaxConn int //the max connection num of client allow NowConn int32 //the connection num of now WebUserName string //the username of web login WebPassword string //the password of web login ConfigConnAllow bool //is allow connected by config file sync.RWMutex } func NewClient(vKey string, noStore bool, noDisplay bool) *Client { return &Client{ Cnf: new(Config), Id: 0, VerifyKey: vKey, Addr: "", Remark: "", Status: true, IsConnect: false, RateLimit: 0, Flow: new(Flow), Rate: nil, NoStore: noStore, RWMutex: sync.RWMutex{}, NoDisplay: noDisplay, } } func (s *Client) CutConn() { atomic.AddInt32(&s.NowConn, 1) } func (s *Client) AddConn() { atomic.AddInt32(&s.NowConn, -1) } func (s *Client) GetConn() bool { if s.MaxConn == 0 || int(s.NowConn) < s.MaxConn { s.CutConn() return true } return false } func (s *Client) HasTunnel(t *Tunnel) (exist bool) { GetCsvDb().Tasks.Range(func(key, value interface{}) bool { v := value.(*Tunnel) if v.Client.Id == s.Id && v.Port == t.Port { exist = true return false } return true }) return } func (s *Client) HasHost(h *Host) bool { var has bool GetCsvDb().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 return false } return true }) return has } type Tunnel struct { Id int //Id Port int //服务端监听端口 ServerIp string Mode string //启动方式 Status bool //设置是否开启 RunStatus bool //当前运行状态 Client *Client //所属客户端id Ports string //客户端与服务端传递 Flow *Flow Password string //私密模式密码,唯一 Remark string //备注 TargetAddr string NoStore bool LocalPath string StripPre string Target *Target Health sync.RWMutex } type Health struct { HealthCheckTimeout int HealthMaxFail int HealthCheckInterval int HealthNextTime time.Time HealthMap map[string]int HttpHealthUrl string HealthRemoveArr []string HealthCheckType string HealthCheckTarget string sync.RWMutex } type Target struct { nowIndex int TargetStr string TargetArr []string //目标 sync.RWMutex } func (s *Target) GetRandomTarget() (string, error) { if s.TargetArr == nil { s.TargetArr = strings.Split(s.TargetStr, "\n") } if len(s.TargetArr) == 1 { return s.TargetArr[0], nil } if len(s.TargetArr) == 0 { return "", errors.New("all inward-bending targets are offline") } s.Lock() defer s.Unlock() if s.nowIndex >= len(s.TargetArr)-1 { s.nowIndex = -1 } 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 }