redo web UI |web close| client log |system info |p2p |max、ump optimization

This commit is contained in:
刘河
2019-03-01 17:23:14 +08:00
parent 534d428c6d
commit f526c56784
82 changed files with 15199 additions and 4561 deletions

View File

@@ -1,16 +1,11 @@
package common
const (
CONN_DATA_SEQ = "*#*"
COMPRESS_NONE_ENCODE = iota
COMPRESS_NONE_DECODE
COMPRESS_SNAPY_ENCODE
COMPRESS_SNAPY_DECODE
CONN_DATA_SEQ = "*#*" //Separator
VERIFY_EER = "vkey"
VERIFY_SUCCESS = "sucs"
WORK_MAIN = "main"
WORK_CHAN = "chan"
WORK_SEND_STATUS = "sdst"
WORK_CONFIG = "conf"
WORK_REGISTER = "rgst"
WORK_SECRET = "sert"
@@ -18,14 +13,12 @@ const (
WORK_P2P_VISITOR = "p2pv"
WORK_P2P_PROVIDER = "p2pp"
WORK_STATUS = "stus"
RES_SIGN = "sign"
RES_MSG = "msg0"
RES_CLOSE = "clse"
NEW_CONN = "conn" //新连接标志
NEW_UDP_CONN = "udpc" //p2p udp conn
NEW_TASK = "task" //新连接标志
NEW_CONF = "conf" //新连接标志
NEW_HOST = "host" //新连接标志
NEW_TASK = "task"
NEW_CONF = "conf"
NEW_HOST = "host"
CONN_TCP = "tcp"
CONN_UDP = "udp"
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
@@ -33,9 +26,7 @@ Content-Type: text/plain; charset=utf-8
WWW-Authenticate: Basic realm="easyProxy"
401 Unauthorized`
IO_EOF = "PROXYEOF"
ConnectionFailBytes = `HTTP/1.1 404 Not Found
`
)

View File

@@ -16,19 +16,6 @@ import (
"strings"
)
//Judging Compression Mode
func GetCompressType(compress string) (int, int) {
switch compress {
case "":
return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
case "snappy":
return COMPRESS_SNAPY_DECODE, COMPRESS_SNAPY_ENCODE
default:
return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
}
return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
}
//Get the corresponding IP address through domain name
func GetHostByName(hostname string) string {
if !DomainCheck(hostname) {
@@ -185,6 +172,7 @@ func BinaryWrite(raw *bytes.Buffer, v ...string) {
binary.Write(raw, binary.LittleEndian, buffer.Bytes())
}
//inArray str interface
func InStrArr(arr []string, val string) bool {
for _, v := range arr {
if v == val {
@@ -194,6 +182,7 @@ func InStrArr(arr []string, val string) bool {
return false
}
//inArray int interface
func InIntArr(arr []int, val int) bool {
for _, v := range arr {
if v == val {
@@ -203,6 +192,7 @@ func InIntArr(arr []int, val int) bool {
return false
}
//format ports str to a int array
func GetPorts(p string) []int {
var ps []int
arr := strings.Split(p, ",")
@@ -277,3 +267,12 @@ func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
defer pool.PutBufPoolCopy(buf)
return written, err
}
//send this ip forget to get a local udp port
func GetLocalUdpAddr() (net.Conn, error) {
tmpConn, err := net.Dial("udp", "114.114.114.114:53")
if err != nil {
return nil, err
}
return tmpConn, tmpConn.Close()
}

View File

@@ -21,6 +21,7 @@ type LocalServer struct {
Type string
Port int
Password string
Target string
}
type Config struct {
content string
@@ -115,7 +116,7 @@ func dealCommon(s string) *CommonConfig {
case "password":
c.Cnf.P = item[1]
case "compress":
c.Cnf.Compress = item[1]
c.Cnf.Compress = common.GetBoolByStr(item[1])
case "crypt":
c.Cnf.Crypt = common.GetBoolByStr(item[1])
case "proxy_socks5_url":
@@ -202,6 +203,8 @@ func delLocalService(s string) *LocalServer {
l.Port = common.GetIntNoErrByStr(item[1])
case "password":
l.Password = item[1]
case "target":
l.Target = item[1]
}
}
return l

View File

@@ -69,36 +69,34 @@ func (s *Conn) GetHost() (method, address string, rb []byte, err error, r *http.
return
}
func (s *Conn) GetLenContent() (b []byte, err error) {
func (s *Conn) GetShortLenContent() (b []byte, err error) {
var l int
if l, err = s.GetLen(); err != nil {
return
}
b, err = s.ReadLen(l)
return
if l < 0 || l > 32<<10 {
err = errors.New("read length error")
return
}
return s.GetShortContent(l)
}
func (s *Conn) GetShortContent(l int) (b []byte, err error) {
buf := make([]byte, l)
return buf, binary.Read(s, binary.LittleEndian, &buf)
}
//读取指定长度内容
func (s *Conn) ReadLen(cLen int) ([]byte, error) {
if cLen > pool.PoolSize {
return nil, errors.New("长度错误" + strconv.Itoa(cLen))
func (s *Conn) ReadLen(cLen int, buf []byte) (int, error) {
if cLen > len(buf) {
return 0, errors.New("长度错误" + strconv.Itoa(cLen))
}
var buf []byte
if cLen < pool.PoolSizeSmall {
buf = pool.BufPoolSmall.Get().([]byte)[:cLen]
//TODO 回收
//defer pool.PutBufPoolSmall(buf)
} else {
buf = pool.BufPoolMax.Get().([]byte)[:cLen]
//defer pool.PutBufPoolMax(buf)
if n, err := io.ReadFull(s, buf[:cLen]); err != nil || n != cLen {
return n, errors.New("Error reading specified length " + err.Error())
}
if n, err := io.ReadFull(s, buf); err != nil || n != cLen {
return buf, errors.New("Error reading specified length " + err.Error())
}
return buf, nil
return cLen, nil
}
//read length or id (content length=4)
func (s *Conn) GetLen() (int, error) {
var l int32
err := binary.Read(s, binary.LittleEndian, &l)
@@ -115,26 +113,8 @@ func (s *Conn) WriteLenContent(buf []byte) (err error) {
//read flag
func (s *Conn) ReadFlag() (string, error) {
val, err := s.ReadLen(4)
if err != nil {
return "", err
}
return string(val), err
}
//read connect status
func (s *Conn) GetConnStatus() (id int, status bool, err error) {
id, err = s.GetLen()
if err != nil {
return
}
var b []byte
if b, err = s.ReadLen(1); err != nil {
return
} else {
status = common.GetBoolByStr(string(b[0]))
}
return
buf := make([]byte, 4)
return string(buf), binary.Read(s, binary.LittleEndian, &buf)
}
//设置连接为长连接
@@ -179,102 +159,32 @@ func (s *Conn) SetKcpReadDeadline(t time.Duration) {
s.Conn.(*kcp.UDPSession).SetReadDeadline(time.Now().Add(time.Duration(t) * time.Second))
}
//单独读(加密|压缩)
func (s *Conn) ReadFrom(b []byte, compress int, crypt bool, rate *rate.Rate) (int, error) {
if common.COMPRESS_SNAPY_DECODE == compress {
return NewSnappyConn(s.Conn, crypt, rate).Read(b)
}
return NewCryptConn(s.Conn, crypt, rate).Read(b)
}
//单独写(加密|压缩)
func (s *Conn) WriteTo(b []byte, compress int, crypt bool, rate *rate.Rate) (n int, err error) {
if common.COMPRESS_SNAPY_ENCODE == compress {
return NewSnappyConn(s.Conn, crypt, rate).Write(b)
}
return NewCryptConn(s.Conn, crypt, rate).Write(b)
}
//send msg
func (s *Conn) SendMsg(content []byte, link *Link) (n int, err error) {
/*
The msg info is formed as follows:
+----+--------+
|id | content |
+----+--------+
| 4 | ... |
+----+--------+
*/
s.Lock()
defer s.Unlock()
if err = binary.Write(s.Conn, binary.LittleEndian, int32(link.Id)); err != nil {
return
}
n, err = s.WriteTo(content, link.En, link.Crypt, link.Rate)
return
}
//get msg content from conn
func (s *Conn) GetMsgContent(link *Link) (content []byte, err error) {
s.Lock()
defer s.Unlock()
buf := pool.BufPoolCopy.Get().([]byte)
if n, err := s.ReadFrom(buf, link.De, link.Crypt, link.Rate); err == nil {
content = buf[:n]
}
return
}
//send info for link
func (s *Conn) SendLinkInfo(link *Link) (int, error) {
/*
The link info is formed as follows:
+----------+------+----------+------+----------+-----+
| id | len | type | hostlen | host | en | de |crypt |
+----------+------+----------+------+---------+------+
| 4 | 4 | 3 | 4 | host | 1 | 1 | 1 |
+----------+------+----------+------+----+----+------+
*/
raw := bytes.NewBuffer([]byte{})
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_CONN))
binary.Write(raw, binary.LittleEndian, int32(14+len(link.Host)))
binary.Write(raw, binary.LittleEndian, int32(link.Id))
binary.Write(raw, binary.LittleEndian, []byte(link.ConnType))
binary.Write(raw, binary.LittleEndian, int32(len(link.Host)))
binary.Write(raw, binary.LittleEndian, []byte(link.Host))
binary.Write(raw, binary.LittleEndian, []byte(strconv.Itoa(link.En)))
binary.Write(raw, binary.LittleEndian, []byte(strconv.Itoa(link.De)))
binary.Write(raw, binary.LittleEndian, []byte(common.GetStrByBool(link.Crypt)))
common.BinaryWrite(raw, link.ConnType, link.Host, common.GetStrByBool(link.Compress), common.GetStrByBool(link.Crypt), link.RemoteAddr)
s.Lock()
defer s.Unlock()
return s.Write(raw.Bytes())
}
//get link info from conn
func (s *Conn) GetLinkInfo() (lk *Link, err error) {
s.Lock()
defer s.Unlock()
var hostLen, n int
var buf []byte
if n, err = s.GetLen(); err != nil {
return
}
lk = new(Link)
if buf, err = s.ReadLen(n); err != nil {
var l int
buf := pool.BufPoolMax.Get().([]byte)
defer pool.PutBufPoolMax(buf)
if l, err = s.GetLen(); err != nil {
return
}
if lk.Id, err = GetLenByBytes(buf[:4]); err != nil {
return
}
lk.ConnType = string(buf[4:7])
if hostLen, err = GetLenByBytes(buf[7:11]); err != nil {
} else if _, err = s.ReadLen(l, buf); err != nil {
return
} else {
lk.Host = string(buf[11 : 11+hostLen])
lk.En = common.GetIntNoErrByStr(string(buf[11+hostLen]))
lk.De = common.GetIntNoErrByStr(string(buf[12+hostLen]))
lk.Crypt = common.GetBoolByStr(string(buf[13+hostLen]))
lk.MsgCh = make(chan []byte)
lk.StatusCh = make(chan bool)
arr := strings.Split(string(buf[:l]), common.CONN_DATA_SEQ)
lk.ConnType = arr[0]
lk.Host = arr[1]
lk.Compress = common.GetBoolByStr(arr[2])
lk.Crypt = common.GetBoolByStr(arr[3])
lk.RemoteAddr = arr[4]
}
return
}
@@ -297,6 +207,7 @@ 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
@@ -314,13 +225,14 @@ func (s *Conn) WriteAddFail() error {
//get task info
func (s *Conn) GetHostInfo() (h *file.Host, err error) {
var l int
var b []byte
buf := pool.BufPoolMax.Get().([]byte)
defer pool.PutBufPoolMax(buf)
if l, err = s.GetLen(); err != nil {
return
} else if b, err = s.ReadLen(l); err != nil {
} else if _, err = s.ReadLen(l, buf); err != nil {
return
} else {
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
arr := strings.Split(string(buf[:l]), common.CONN_DATA_SEQ)
h = new(file.Host)
h.Id = file.GetCsvDb().GetHostId()
h.Host = arr[0]
@@ -347,7 +259,7 @@ func (s *Conn) SendConfigInfo(c *config.CommonConfig) (int, error) {
*/
raw := bytes.NewBuffer([]byte{})
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_CONF))
common.BinaryWrite(raw, c.Cnf.U, c.Cnf.P, common.GetStrByBool(c.Cnf.Crypt), c.Cnf.Compress, strconv.Itoa(c.Client.RateLimit),
common.BinaryWrite(raw, c.Cnf.U, c.Cnf.P, common.GetStrByBool(c.Cnf.Crypt), common.GetStrByBool(c.Cnf.Compress), strconv.Itoa(c.Client.RateLimit),
strconv.Itoa(int(c.Client.Flow.FlowLimit)), strconv.Itoa(c.Client.MaxConn), c.Client.Remark)
s.Lock()
defer s.Unlock()
@@ -357,23 +269,23 @@ func (s *Conn) SendConfigInfo(c *config.CommonConfig) (int, error) {
//get task info
func (s *Conn) GetConfigInfo() (c *file.Client, err error) {
var l int
var b []byte
buf := pool.BufPoolMax.Get().([]byte)
defer pool.PutBufPoolMax(buf)
if l, err = s.GetLen(); err != nil {
return
} else if b, err = s.ReadLen(l); err != nil {
} else if _, err = s.ReadLen(l, buf); err != nil {
return
} else {
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
arr := strings.Split(string(buf[:l]), common.CONN_DATA_SEQ)
c = file.NewClient("", true, false)
c.Cnf.U = arr[0]
c.Cnf.P = arr[1]
c.Cnf.Crypt = common.GetBoolByStr(arr[2])
c.Cnf.Compress = arr[3]
c.Cnf.Compress = common.GetBoolByStr(arr[3])
c.RateLimit = common.GetIntNoErrByStr(arr[4])
c.Flow.FlowLimit = int64(common.GetIntNoErrByStr(arr[5]))
c.MaxConn = common.GetIntNoErrByStr(arr[6])
c.Remark = arr[7]
c.Cnf.CompressDecode, c.Cnf.CompressDecode = common.GetCompressType(arr[3])
}
return
}
@@ -399,13 +311,14 @@ func (s *Conn) SendTaskInfo(t *file.Tunnel) (int, error) {
//get task info
func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
var l int
var b []byte
buf := pool.BufPoolMax.Get().([]byte)
defer pool.PutBufPoolMax(buf)
if l, err = s.GetLen(); err != nil {
return
} else if b, err = s.ReadLen(l); err != nil {
} else if _, err = s.ReadLen(l, buf); err != nil {
return
} else {
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
arr := strings.Split(string(buf[:l]), common.CONN_DATA_SEQ)
t = new(file.Tunnel)
t.Mode = arr[0]
t.Ports = arr[1]
@@ -421,30 +334,6 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
return
}
func (s *Conn) WriteWriteSuccess(id int) error {
return binary.Write(s.Conn, binary.LittleEndian, int32(id))
}
//write connect success
func (s *Conn) WriteSuccess(id int) (int, error) {
raw := bytes.NewBuffer([]byte{})
binary.Write(raw, binary.LittleEndian, int32(id))
binary.Write(raw, binary.LittleEndian, []byte("1"))
s.Lock()
defer s.Unlock()
return s.Write(raw.Bytes())
}
//write connect fail
func (s *Conn) WriteFail(id int) (int, error) {
raw := bytes.NewBuffer([]byte{})
binary.Write(raw, binary.LittleEndian, int32(id))
binary.Write(raw, binary.LittleEndian, []byte("0"))
s.Lock()
defer s.Unlock()
return s.Write(raw.Bytes())
}
//close
func (s *Conn) Close() error {
return s.Conn.Close()
@@ -460,16 +349,6 @@ func (s *Conn) Read(b []byte) (int, error) {
return s.Conn.Read(b)
}
//write error
func (s *Conn) WriteError() (int, error) {
return s.Write([]byte(common.RES_MSG))
}
//write sign flag
func (s *Conn) WriteSign() (int, error) {
return s.Write([]byte(common.RES_SIGN))
}
//write sign flag
func (s *Conn) WriteClose() (int, error) {
return s.Write([]byte(common.RES_CLOSE))
@@ -495,6 +374,7 @@ func (s *Conn) WriteChan() (int, error) {
defer s.Unlock()
return s.Write([]byte(common.WORK_CHAN))
}
//获取长度+内容
func GetLenBytes(buf []byte) (b []byte, err error) {
raw := bytes.NewBuffer([]byte{})
@@ -508,16 +388,6 @@ func GetLenBytes(buf []byte) (b []byte, err error) {
return
}
//解析出长度
func GetLenByBytes(buf []byte) (int, error) {
nlen := binary.LittleEndian.Uint32(buf)
if nlen <= 0 {
return 0, errors.New("数据长度错误")
}
return int(nlen), nil
}
func SetUdpSession(sess *kcp.UDPSession) {
sess.SetStreamMode(true)
sess.SetWindowSize(1024, 1024)
@@ -528,3 +398,40 @@ func SetUdpSession(sess *kcp.UDPSession) {
sess.SetACKNoDelay(true)
sess.SetWriteDelay(false)
}
//conn1 mux conn
func CopyWaitGroup(conn1, conn2 io.ReadWriteCloser, crypt bool, snappy bool, rate *rate.Rate, flow *file.Flow) {
var in, out int64
var wg sync.WaitGroup
conn1 = GetConn(conn1, crypt, snappy, rate)
go func(in *int64) {
wg.Add(1)
*in, _ = common.CopyBuffer(conn1, conn2)
conn1.Close()
conn2.Close()
wg.Done()
}(&in)
out, _ = common.CopyBuffer(conn2, conn1)
conn1.Close()
conn2.Close()
wg.Wait()
if flow != nil {
flow.Add(in, out)
}
}
//get crypt or snappy conn
func GetConn(conn io.ReadWriteCloser, crypt, snappy bool, rate *rate.Rate) (io.ReadWriteCloser) {
if crypt {
conn = NewCryptConn(conn, true, rate)
} else if snappy {
conn = NewSnappyConn(conn, crypt, rate)
}
return conn
}
//read length or id (content length=4)
func GetLen(reader io.Reader) (int, error) {
var l int32
return int(l), binary.Read(reader, binary.LittleEndian, &l)
}

View File

@@ -1,13 +1,5 @@
package conn
import (
"github.com/cnlh/nps/lib/common"
"github.com/cnlh/nps/lib/file"
"github.com/cnlh/nps/lib/pool"
"github.com/cnlh/nps/lib/rate"
"net"
)
type Secret struct {
Password string
Conn *Conn
@@ -21,93 +13,19 @@ func NewSecret(p string, conn *Conn) *Secret {
}
type Link struct {
Id int //id
ConnType string //连接类型
Host string //目标
En int //加密
De int //解密
Crypt bool //加密
Conn *Conn
Flow *file.Flow
UdpListener *net.UDPConn
Rate *rate.Rate
UdpRemoteAddr *net.UDPAddr
MsgCh chan []byte
MsgConn *Conn
StatusCh chan bool
FinishUse bool
ConnType string //连接类型
Host string //目标
Crypt bool //加密
Compress bool
RemoteAddr string
}
func NewLink(id int, connType string, host string, en, de int, crypt bool, c *Conn, flow *file.Flow, udpListener *net.UDPConn, rate *rate.Rate, UdpRemoteAddr *net.UDPAddr) *Link {
func NewLink(connType string, host string, crypt bool, compress bool, remoteAddr string) *Link {
return &Link{
Id: id,
ConnType: connType,
Host: host,
En: en,
De: de,
Crypt: crypt,
Conn: c,
Flow: flow,
UdpListener: udpListener,
Rate: rate,
UdpRemoteAddr: UdpRemoteAddr,
MsgCh: make(chan []byte),
StatusCh: make(chan bool),
RemoteAddr: remoteAddr,
ConnType: connType,
Host: host,
Crypt: crypt,
Compress: compress,
}
}
func (s *Link) RunWrite() {
go func() {
for {
select {
case content := <-s.MsgCh:
if len(content) == len(common.IO_EOF) && string(content) == common.IO_EOF {
s.FinishUse = true
if s.Conn != nil {
s.Conn.Close()
}
return
} else {
if s.Conn == nil {
return
}
if s.UdpListener != nil && s.UdpRemoteAddr != nil {
s.UdpListener.WriteToUDP(content, s.UdpRemoteAddr)
} else {
s.Conn.Write(content)
}
if s.Flow != nil {
s.Flow.Add(0, len(content))
}
if s.ConnType == common.CONN_UDP {
return
}
s.MsgConn.WriteWriteSuccess(s.Id)
}
pool.PutBufPoolCopy(content)
}
}
}()
}
func (s *Link) RunRead(msgConn *Conn) {
buf := pool.BufPoolCopy.Get().([]byte)
for {
if n, err := s.Conn.Read(buf); err != nil {
msgConn.SendMsg([]byte(common.IO_EOF), s)
break
} else {
if _, err := msgConn.SendMsg(buf[:n], s); err != nil {
msgConn.Close()
break
}
if s.ConnType == common.CONN_UDP {
break
}
if s.Flow != nil {
s.Flow.Add(n, 0)
}
}
<-s.StatusCh
}
pool.PutBufPoolCopy(buf)
}

View File

@@ -2,17 +2,18 @@ package conn
import (
"github.com/cnlh/nps/lib/crypt"
"github.com/cnlh/nps/lib/pool"
"github.com/cnlh/nps/lib/rate"
"net"
"io"
)
type CryptConn struct {
conn net.Conn
conn io.ReadWriteCloser
crypt bool
rate *rate.Rate
}
func NewCryptConn(conn net.Conn, crypt bool, rate *rate.Rate) *CryptConn {
func NewCryptConn(conn io.ReadWriteCloser, crypt bool, rate *rate.Rate) *CryptConn {
c := new(CryptConn)
c.conn = conn
c.crypt = crypt
@@ -43,19 +44,20 @@ func (s *CryptConn) Read(b []byte) (n int, err error) {
var lens int
var buf []byte
var rb []byte
c := NewConn(s.conn)
if lens, err = c.GetLen(); err != nil {
if lens, err = GetLen(s.conn); err != nil || lens > len(b) || lens < 0 {
return
}
if buf, err = c.ReadLen(lens); err != nil {
buf = pool.BufPool.Get().([]byte)
defer pool.BufPool.Put(buf)
if n, err = io.ReadFull(s.conn, buf[:lens]); err != nil {
return
}
if s.crypt {
if rb, err = crypt.AesDecrypt(buf, []byte(cryptKey)); err != nil {
if rb, err = crypt.AesDecrypt(buf[:lens], []byte(cryptKey)); err != nil {
return
}
} else {
rb = buf
rb = buf[:lens]
}
copy(b, rb)
n = len(rb)
@@ -64,3 +66,7 @@ func (s *CryptConn) Read(b []byte) (n int, err error) {
}
return
}
func (s *CryptConn) Close() error {
return s.conn.Close()
}

View File

@@ -4,7 +4,7 @@ import (
"github.com/cnlh/nps/lib/pool"
"github.com/cnlh/nps/lib/rate"
"github.com/cnlh/nps/vender/github.com/golang/snappy"
"net"
"io"
)
type SnappyConn struct {
@@ -13,7 +13,7 @@ type SnappyConn struct {
rate *rate.Rate
}
func NewSnappyConn(conn net.Conn, crypt bool, rate *rate.Rate) *SnappyConn {
func NewSnappyConn(conn io.ReadWriteCloser, crypt bool, rate *rate.Rate) *SnappyConn {
c := new(SnappyConn)
c.w = snappy.NewBufferedWriter(conn)
c.r = snappy.NewReader(conn)
@@ -48,3 +48,8 @@ func (s *SnappyConn) Read(b []byte) (n int, err error) {
}
return
}
func (s *SnappyConn) Close() error {
s.w.Close()
return s.w.Close()
}

View File

@@ -124,6 +124,7 @@ func (s *Csv) GetTaskId() int {
s.TaskIncreaseId++
return s.TaskIncreaseId
}
func (s *Csv) GetHostId() int {
s.Lock()
defer s.Unlock()
@@ -147,7 +148,7 @@ func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (int, error) {
func (s *Csv) NewTask(t *Tunnel) error {
for _, v := range s.Tasks {
if v.Mode == "secretServer" && v.Password == t.Password {
if v.Mode == "secret" && v.Password == t.Password {
return errors.New(fmt.Sprintf("Secret mode keys %s must be unique", t.Password))
}
}
@@ -256,7 +257,7 @@ func (s *Csv) LoadClientFromCsv() {
U: item[4],
P: item[5],
Crypt: common.GetBoolByStr(item[6]),
Compress: item[7],
Compress: common.GetBoolByStr(item[7]),
},
MaxConn: common.GetIntNoErrByStr(item[10]),
}
@@ -327,10 +328,14 @@ func (s *Csv) IsHostExist(h *Host) bool {
return false
}
func (s *Csv) NewHost(t *Host) {
func (s *Csv) NewHost(t *Host) error {
if s.IsHostExist(t) {
return errors.New("host has exist")
}
t.Flow = new(Flow)
s.Hosts = append(s.Hosts, t)
s.StoreHostToCsv()
return nil
}
func (s *Csv) UpdateHost(t *Host) error {
@@ -535,7 +540,7 @@ func (s *Csv) StoreClientsToCsv() {
client.Cnf.U,
client.Cnf.P,
common.GetStrByBool(client.Cnf.Crypt),
client.Cnf.Compress,
strconv.FormatBool(client.Cnf.Compress),
strconv.Itoa(client.RateLimit),
strconv.Itoa(int(client.Flow.FlowLimit)),
strconv.Itoa(int(client.MaxConn)),

View File

@@ -2,7 +2,6 @@ package file
import (
"github.com/cnlh/nps/lib/rate"
"math"
"strings"
"sync"
)
@@ -14,7 +13,7 @@ type Flow struct {
sync.RWMutex
}
func (s *Flow) Add(in, out int) {
func (s *Flow) Add(in, out int64) {
s.Lock()
defer s.Unlock()
s.InletFlow += int64(in)
@@ -57,15 +56,6 @@ func NewClient(vKey string, noStore bool, noDisplay bool) *Client {
NoDisplay: noDisplay,
}
}
func (s *Client) GetId() int {
s.Lock()
defer s.Unlock()
if s.id == math.MaxInt32 {
s.id = 0
}
s.id++
return s.id
}
func (s *Client) CutConn() {
s.Lock()
@@ -104,12 +94,10 @@ type Tunnel struct {
}
type Config struct {
U string //socks5验证用户名
P string //socks5验证密码
Compress string //压缩方式
Crypt bool //是否加密
CompressEncode int //加密方式
CompressDecode int //解密方式
U string //socks5验证用户名
P string //socks5验证密码
Compress bool //压缩方式
Crypt bool //是否加密
}
type Host struct {

View File

@@ -10,7 +10,6 @@ import (
type conn struct {
net.Conn
readMsgCh chan []byte
getStatusCh chan struct{}
connStatusOkCh chan struct{}
connStatusFailCh chan struct{}
@@ -18,8 +17,14 @@ type conn struct {
writeTimeOut time.Time
sendMsgCh chan *msg //mux
sendStatusCh chan int32 //mux
readBuffer []byte
startRead int //now read position
endRead int //now end read
readFlag bool
readCh chan struct{}
connId int32
isClose bool
readWait bool
mux *Mux
}
@@ -37,7 +42,8 @@ func NewMsg(connId int32, content []byte) *msg {
func NewConn(connId int32, mux *Mux, sendMsgCh chan *msg, sendStatusCh chan int32) *conn {
return &conn{
readMsgCh: make(chan []byte),
readCh: make(chan struct{}),
readBuffer: pool.BufPoolCopy.Get().([]byte),
getStatusCh: make(chan struct{}),
connStatusOkCh: make(chan struct{}),
connStatusFailCh: make(chan struct{}),
@@ -51,75 +57,92 @@ func NewConn(connId int32, mux *Mux, sendMsgCh chan *msg, sendStatusCh chan int3
}
}
func (s *conn) Read(buf []byte) (int, error) {
func (s *conn) Read(buf []byte) (n int, err error) {
if s.isClose {
return 0, errors.New("the conn has closed")
}
var b []byte
if t := s.readTimeOut.Sub(time.Now()); t > 0 {
timer := time.NewTimer(t)
select {
case <-timer.C:
s.Close()
return 0, errors.New("read timeout")
case b = <-s.readMsgCh:
if s.endRead-s.startRead == 0 {
s.readWait = true
if t := s.readTimeOut.Sub(time.Now()); t > 0 {
timer := time.NewTimer(t)
select {
case <-timer.C:
s.readWait = false
return 0, errors.New("read timeout")
case <-s.readCh:
}
} else {
<-s.readCh
}
} else {
b = <-s.readMsgCh
}
defer pool.PutBufPoolCopy(b)
s.readWait = false
if s.isClose {
return 0, io.EOF
}
s.sendStatusCh <- s.connId
return copy(buf, b), nil
if len(buf) < s.endRead-s.startRead {
n = copy(buf, s.readBuffer[s.startRead:s.startRead+len(buf)])
s.startRead += n
} else {
n = copy(buf, s.readBuffer[s.startRead:s.endRead])
s.startRead = 0
s.endRead = 0
s.sendStatusCh <- s.connId
}
return
}
func (s *conn) Write(buf []byte) (int, error) {
if s.isClose {
return 0, errors.New("the conn has closed")
}
ch := make(chan struct{})
go s.write(buf, ch)
if t := s.writeTimeOut.Sub(time.Now()); t > 0 {
timer := time.NewTimer(t)
select {
case <-timer.C:
s.Close()
return 0, errors.New("write timeout")
case s.sendMsgCh <- NewMsg(s.connId, buf):
case <-ch:
}
} else {
s.sendMsgCh <- NewMsg(s.connId, buf)
<-ch
}
if t := s.writeTimeOut.Sub(time.Now()); t > 0 {
timer := time.NewTimer(t)
select {
case <-timer.C:
s.Close()
return 0, errors.New("write timeout")
case <-s.getStatusCh:
}
} else {
<-s.getStatusCh
}
if s.isClose {
return 0, io.EOF
}
return len(buf), nil
}
func (s *conn) write(buf []byte, ch chan struct{}) {
start := 0
l := len(buf)
for {
if l-start > pool.PoolSizeCopy {
s.sendMsgCh <- NewMsg(s.connId, buf[start:start+pool.PoolSizeCopy])
start += pool.PoolSizeCopy
<-s.getStatusCh
} else {
s.sendMsgCh <- NewMsg(s.connId, buf[start:l])
<-s.getStatusCh
break
}
}
ch <- struct{}{}
}
func (s *conn) Close() error {
if s.isClose {
return errors.New("the conn has closed")
}
s.isClose = true
pool.PutBufPoolCopy(s.readBuffer)
close(s.getStatusCh)
close(s.readMsgCh)
close(s.connStatusOkCh)
close(s.connStatusFailCh)
s.sendMsgCh <- NewMsg(s.connId, nil)
close(s.readCh)
if !s.mux.isClose {
s.sendMsgCh <- NewMsg(s.connId, nil)
}
return nil
}

View File

@@ -23,7 +23,7 @@ func NewConnMap() *connMap {
func (s *connMap) Get(id int32) (*conn, bool) {
s.Lock()
defer s.Unlock()
if v, ok := s.connMap[id]; ok {
if v, ok := s.connMap[id]; ok && v != nil {
return v, true
}
return nil, false

View File

@@ -125,6 +125,9 @@ func (s *Mux) writeSession() {
raw.Reset()
select {
case msg := <-s.sendMsgCh:
if msg == nil {
break
}
if msg.content == nil { //close
binary.Write(raw, binary.LittleEndian, MUX_CONN_CLOSE)
binary.Write(raw, binary.LittleEndian, msg.connId)
@@ -152,8 +155,12 @@ func (s *Mux) writeSession() {
func (s *Mux) readSession() {
go func() {
raw := bytes.NewBuffer([]byte{})
buf := pool.BufPoolCopy.Get().([]byte)
defer pool.PutBufPoolCopy(buf)
for {
var flag, i int32
var n int
var err error
if binary.Read(s.conn, binary.LittleEndian, &flag) == nil {
if binary.Read(s.conn, binary.LittleEndian, &i) != nil {
break
@@ -170,19 +177,18 @@ func (s *Mux) readSession() {
continue
case MUX_PING_FLAG: //ping
continue
case MUX_NEW_MSG:
if n, err = ReadLenBytes(buf, s.conn); err != nil {
break
}
}
if conn, ok := s.connMap.Get(i); ok {
if conn, ok := s.connMap.Get(i); ok && !conn.isClose {
switch flag {
case MUX_NEW_MSG: //new msg from remote conn
buf := pool.BufPoolCopy.Get().([]byte)
if n, err := ReadLenBytes(buf, s.conn); err == nil {
if !conn.isClose {
conn.readMsgCh <- buf[:n]
} else {
pool.PutBufPoolCopy(buf)
}
} else { //read len bytes error,the mux has broken
break
copy(conn.readBuffer, buf[:n])
conn.endRead = n
if conn.readWait {
conn.readCh <- struct{}{}
}
case MUX_MSG_SEND_OK: //the remote has read
conn.getStatusCh <- struct{}{}

View File

@@ -2,6 +2,7 @@ package mux
import (
"github.com/cnlh/nps/lib/common"
conn3 "github.com/cnlh/nps/lib/conn"
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
"log"
"net"
@@ -35,8 +36,8 @@ func TestNewMux(t *testing.T) {
if err != nil {
log.Fatalln(err)
}
go common.CopyBuffer(c2, c)
common.CopyBuffer(c, c2)
go common.CopyBuffer(c2, conn3.NewCryptConn(c, true, nil))
common.CopyBuffer(conn3.NewCryptConn(c, true, nil), c2)
c.Close()
c2.Close()
}(c)
@@ -59,8 +60,8 @@ func TestNewMux(t *testing.T) {
if err != nil {
log.Fatalln(err)
}
go common.CopyBuffer(tmpCpnn, conn)
common.CopyBuffer(conn, tmpCpnn)
go common.CopyBuffer(conn3.NewCryptConn(tmpCpnn, true, nil), conn)
common.CopyBuffer(conn, conn3.NewCryptConn(tmpCpnn, true, nil))
conn.Close()
tmpCpnn.Close()
}(conn)

View File

@@ -7,7 +7,7 @@ import (
const PoolSize = 64 * 1024
const PoolSizeSmall = 100
const PoolSizeUdp = 1472
const PoolSizeCopy = 32 * 1024
const PoolSizeCopy = 32 << 6
var BufPool = sync.Pool{
New: func() interface{} {
@@ -42,7 +42,6 @@ func PutBufPoolUdp(buf []byte) {
}
}
func PutBufPoolCopy(buf []byte) {
if cap(buf) == PoolSizeCopy {
BufPoolCopy.Put(buf[:PoolSizeCopy])

View File

@@ -1,6 +1,6 @@
package version
const VERSION = "0.0.16"
const VERSION = "0.17.0"
func GetVersion() string {
return VERSION