mirror of
https://github.com/ehang-io/nps.git
synced 2025-09-02 03:16:53 +00:00
redo web UI |web close| client log |system info |p2p |max、ump optimization
This commit is contained in:
@@ -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
|
||||
|
||||
`
|
||||
|
||||
)
|
||||
|
@@ -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()
|
||||
}
|
||||
|
@@ -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
|
||||
|
263
lib/conn/conn.go
263
lib/conn/conn.go
@@ -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)
|
||||
}
|
||||
|
104
lib/conn/link.go
104
lib/conn/link.go
@@ -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)
|
||||
}
|
||||
|
@@ -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()
|
||||
}
|
||||
|
@@ -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()
|
||||
}
|
||||
|
@@ -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)),
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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{}{}
|
||||
|
@@ -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)
|
||||
|
@@ -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])
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package version
|
||||
|
||||
const VERSION = "0.0.16"
|
||||
const VERSION = "0.17.0"
|
||||
|
||||
func GetVersion() string {
|
||||
return VERSION
|
||||
|
Reference in New Issue
Block a user