1
0
ffdfgdfg 5 жил өмнө
parent
commit
1f8e441090

+ 10 - 1
README.md

@@ -197,6 +197,9 @@ nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务
 - 在刚才创建的客户端隧道管理中添加一条socks5代理,填写监听的端口(8003),保存。
 - 在刚才创建的客户端隧道管理中添加一条socks5代理,填写监听的端口(8003),保存。
 - 在外网环境的本机配置socks5代理(例如使用proxifier进行全局代理),ip为公网服务器ip(1.1.1.1),端口为填写的监听端口(8003),即可畅享内网了
 - 在外网环境的本机配置socks5代理(例如使用proxifier进行全局代理),ip为公网服务器ip(1.1.1.1),端口为填写的监听端口(8003),即可畅享内网了
 
 
+**注意**
+经过socks5代理,当收到socks5数据包时socket已经是accept状态。表现是扫描端口全open,建立连接后短时间关闭。若想同内网表现一致,建议远程连接一台设备。
+
 ### http正向代理
 ### http正向代理
 
 
 **适用范围:**  在外网环境下使用http正向代理访问内网站点
 **适用范围:**  在外网环境下使用http正向代理访问内网站点
@@ -375,7 +378,13 @@ server {
 ```
 ```
 (./nps|nps.exe) install
 (./nps|nps.exe) install
 ```
 ```
-安装成功后,对于linux,darwin,将会把配置文件和静态文件放置于/etc/nps/,并将可执行文件nps复制到/usr/bin/nps或者/usr/local/bin/nps,安装成功后可在任何位置执行
+安装成功后,对于linux,darwin,将会把配置文件和静态文件放置于/etc/nps/,并将可执行文件nps复制到/usr/bin/nps或者/usr/local/bin/nps,安装成功后可在任何位置执行,同时也会添加systemd配置。
+
+```
+sudo systemctl enable|disable|start|stop|restart|status nps
+```
+systemd,带有开机自启,自动重启配置,当进程结束后15秒会启动,日志输出至/var/log/nps/nps.log。
+建议采用此方式启动,能够捕获panic信息,便于排查问题。
 
 
 ```
 ```
 nps test|start|stop|restart|status
 nps test|start|stop|restart|status

+ 5 - 0
client/client.go

@@ -49,6 +49,11 @@ retry:
 		time.Sleep(time.Second * 5)
 		time.Sleep(time.Second * 5)
 		goto retry
 		goto retry
 	}
 	}
+	if c == nil {
+		logs.Error("Error data from server, and will be reconnected in five seconds")
+		time.Sleep(time.Second * 5)
+		goto retry
+	}
 	logs.Info("Successful connection with server %s", s.svrAddr)
 	logs.Info("Successful connection with server %s", s.svrAddr)
 	//monitor the connection
 	//monitor the connection
 	go s.ping()
 	go s.ping()

+ 7 - 2
client/control.go

@@ -223,8 +223,13 @@ func NewConn(tp string, vkey string, server string, connType string, proxyUrl st
 	if _, err := c.Write([]byte(crypt.Md5(version.GetVersion()))); err != nil {
 	if _, err := c.Write([]byte(crypt.Md5(version.GetVersion()))); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	if b, err := c.GetShortContent(32); err != nil || crypt.Md5(version.GetVersion()) != string(b) {
-		logs.Error("The client does not match the server version. The current version of the client is", version.GetVersion())
+	b, err := c.GetShortContent(32)
+	if err != nil {
+		logs.Error(err)
+		return nil, err
+	}
+	if crypt.Md5(version.GetVersion()) != string(b) {
+		logs.Error("The client does not match the server version. The current core version of the client is", version.GetVersion())
 		return nil, err
 		return nil, err
 	}
 	}
 	if _, err := c.Write([]byte(common.Getverifyval(vkey))); err != nil {
 	if _, err := c.Write([]byte(common.Getverifyval(vkey))); err != nil {

+ 1 - 1
cmd/nps/nps.go

@@ -61,7 +61,7 @@ func main() {
 		logs.Error("Getting bridge_port error", err)
 		logs.Error("Getting bridge_port error", err)
 		os.Exit(0)
 		os.Exit(0)
 	}
 	}
-	logs.Info("the version of server is %s ,allow client version to be %s", version.VERSION, version.GetVersion())
+	logs.Info("the version of server is %s ,allow client core version to be %s", version.VERSION, version.GetVersion())
 	connection.InitConnectionService()
 	connection.InitConnectionService()
 	crypt.InitTls(filepath.Join(common.GetRunPath(), "conf", "server.pem"), filepath.Join(common.GetRunPath(), "conf", "server.key"))
 	crypt.InitTls(filepath.Join(common.GetRunPath(), "conf", "server.pem"), filepath.Join(common.GetRunPath(), "conf", "server.key"))
 	tool.InitAllowPort()
 	tool.InitAllowPort()

+ 1 - 0
lib/common/const.go

@@ -49,4 +49,5 @@ const (
 	MUX_PING_RETURN
 	MUX_PING_RETURN
 	MUX_PING             int32 = -1
 	MUX_PING             int32 = -1
 	MAXIMUM_SEGMENT_SIZE       = PoolSizeWindow
 	MAXIMUM_SEGMENT_SIZE       = PoolSizeWindow
+	MAXIMUM_WINDOW_SIZE        = 1<<31 - 1
 )
 )

+ 7 - 2
lib/common/netpackager.go

@@ -158,8 +158,10 @@ func (Self *MuxPackager) NewPac(flag uint8, id int32, content ...interface{}) (e
 	Self.Flag = flag
 	Self.Flag = flag
 	Self.Id = id
 	Self.Id = id
 	switch flag {
 	switch flag {
-	case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN:
+	case MUX_PING_FLAG, MUX_PING_RETURN, MUX_NEW_MSG, MUX_NEW_MSG_PART:
+		Self.Content = WindowBuff.Get()
 		err = Self.BasePackager.NewPac(content...)
 		err = Self.BasePackager.NewPac(content...)
+		//logs.Warn(Self.Length, string(Self.Content))
 	case MUX_MSG_SEND_OK:
 	case MUX_MSG_SEND_OK:
 		// MUX_MSG_SEND_OK contains two data
 		// MUX_MSG_SEND_OK contains two data
 		switch content[0].(type) {
 		switch content[0].(type) {
@@ -190,6 +192,7 @@ func (Self *MuxPackager) Pack(writer io.Writer) (err error) {
 	switch Self.Flag {
 	switch Self.Flag {
 	case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN:
 	case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN:
 		err = Self.BasePackager.Pack(writer)
 		err = Self.BasePackager.Pack(writer)
+		WindowBuff.Put(Self.Content)
 	case MUX_MSG_SEND_OK:
 	case MUX_MSG_SEND_OK:
 		err = binary.Write(writer, binary.LittleEndian, Self.Window)
 		err = binary.Write(writer, binary.LittleEndian, Self.Window)
 		if err != nil {
 		if err != nil {
@@ -201,7 +204,6 @@ func (Self *MuxPackager) Pack(writer io.Writer) (err error) {
 }
 }
 
 
 func (Self *MuxPackager) UnPack(reader io.Reader) (err error) {
 func (Self *MuxPackager) UnPack(reader io.Reader) (err error) {
-	Self.BasePackager.clean() // also clean the content
 	err = binary.Read(reader, binary.LittleEndian, &Self.Flag)
 	err = binary.Read(reader, binary.LittleEndian, &Self.Flag)
 	if err != nil {
 	if err != nil {
 		return
 		return
@@ -212,7 +214,10 @@ func (Self *MuxPackager) UnPack(reader io.Reader) (err error) {
 	}
 	}
 	switch Self.Flag {
 	switch Self.Flag {
 	case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN:
 	case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN:
+		Self.Content = WindowBuff.Get() // need get a window buf from pool
+		Self.BasePackager.clean()       // also clean the content
 		err = Self.BasePackager.UnPack(reader)
 		err = Self.BasePackager.UnPack(reader)
+		//logs.Warn("unpack", Self.Length, string(Self.Content))
 	case MUX_MSG_SEND_OK:
 	case MUX_MSG_SEND_OK:
 		err = binary.Read(reader, binary.LittleEndian, &Self.Window)
 		err = binary.Read(reader, binary.LittleEndian, &Self.Window)
 		if err != nil {
 		if err != nil {

+ 2 - 9
lib/common/pool.go

@@ -104,11 +104,7 @@ func (Self *windowBufferPool) Get() (buf []byte) {
 }
 }
 
 
 func (Self *windowBufferPool) Put(x []byte) {
 func (Self *windowBufferPool) Put(x []byte) {
-	if len(x) == PoolSizeWindow {
-		Self.pool.Put(x[:PoolSizeWindow]) // make buf to full
-	} else {
-		x = nil
-	}
+	Self.pool.Put(x[:PoolSizeWindow]) // make buf to full
 }
 }
 
 
 type bufferPool struct {
 type bufferPool struct {
@@ -146,13 +142,10 @@ func (Self *muxPackagerPool) New() {
 }
 }
 
 
 func (Self *muxPackagerPool) Get() *MuxPackager {
 func (Self *muxPackagerPool) Get() *MuxPackager {
-	pack := Self.pool.Get().(*MuxPackager)
-	pack.Content = WindowBuff.Get()
-	return pack
+	return Self.pool.Get().(*MuxPackager)
 }
 }
 
 
 func (Self *muxPackagerPool) Put(pack *MuxPackager) {
 func (Self *muxPackagerPool) Put(pack *MuxPackager) {
-	WindowBuff.Put(pack.Content)
 	Self.pool.Put(pack)
 	Self.pool.Put(pack)
 }
 }
 
 

+ 3 - 0
lib/common/util.go

@@ -268,6 +268,9 @@ func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
 	defer CopyBuff.Put(buf)
 	defer CopyBuff.Put(buf)
 	for {
 	for {
 		nr, er := src.Read(buf)
 		nr, er := src.Read(buf)
+		//if len(pr)>0 && pr[0] && nr > 50 {
+		//	logs.Warn(string(buf[:50]))
+		//}
 		if nr > 0 {
 		if nr > 0 {
 			nw, ew := dst.Write(buf[0:nr])
 			nw, ew := dst.Write(buf[0:nr])
 			if nw > 0 {
 			if nw > 0 {

+ 35 - 3
lib/install/install.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
+	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
@@ -13,6 +14,23 @@ import (
 )
 )
 
 
 func InstallNps() {
 func InstallNps() {
+	unit := `[Unit]
+Description=nps - convenient proxy server
+Documentation=https://github.com/cnlh/nps/
+After=network-online.target remote-fs.target nss-lookup.target
+Wants=network-online.target`
+	service := `[Service]
+Type=simple
+KillMode=process
+Restart=always
+RestartSec=15s
+StandardOutput=append:/var/log/nps/nps.log
+ExecStartPre=/bin/echo 'Starting nps'
+ExecStopPost=/bin/echo 'Stopping nps'
+ExecStart=`
+	install := `[Install]
+WantedBy=multi-user.target`
+
 	path := common.GetInstallPath()
 	path := common.GetInstallPath()
 	if common.FileExists(path) {
 	if common.FileExists(path) {
 		log.Fatalf("the path %s has exist, does not support install", path)
 		log.Fatalf("the path %s has exist, does not support install", path)
@@ -35,21 +53,35 @@ func InstallNps() {
 				log.Fatalln(err)
 				log.Fatalln(err)
 			} else {
 			} else {
 				os.Chmod("/usr/local/bin/nps", 0755)
 				os.Chmod("/usr/local/bin/nps", 0755)
+				service += "/usr/local/bin/nps"
 				log.Println("Executable files have been copied to", "/usr/local/bin/nps")
 				log.Println("Executable files have been copied to", "/usr/local/bin/nps")
 			}
 			}
 		} else {
 		} else {
 			os.Chmod("/usr/bin/nps", 0755)
 			os.Chmod("/usr/bin/nps", 0755)
+			service += "/usr/bin/nps"
 			log.Println("Executable files have been copied to", "/usr/bin/nps")
 			log.Println("Executable files have been copied to", "/usr/bin/nps")
 		}
 		}
-
+		systemd := unit + "\n\n" + service + "\n\n" + install
+		_ = os.Remove("/usr/lib/systemd/system/nps.service")
+		err := ioutil.WriteFile("/usr/lib/systemd/system/nps.service", []byte(systemd), 0644)
+		if err != nil {
+			log.Println("Write systemd service err ", err)
+		}
+		_ = os.Mkdir("/var/log/nps", 644)
 	}
 	}
 	log.Println("install ok!")
 	log.Println("install ok!")
 	log.Println("Static files and configuration files in the current directory will be useless")
 	log.Println("Static files and configuration files in the current directory will be useless")
 	log.Println("The new configuration file is located in", path, "you can edit them")
 	log.Println("The new configuration file is located in", path, "you can edit them")
 	if !common.IsWindows() {
 	if !common.IsWindows() {
-		log.Println("You can start with nps test|start|stop|restart|status anywhere")
+		log.Println(`You can start with:
+sudo systemctl enable|disable|start|stop|restart|status nps
+or:
+nps test|start|stop|restart|status 
+anywhere!`)
 	} else {
 	} else {
-		log.Println("You can copy executable files to any directory and start working with nps.exe test|start|stop|restart|status")
+		log.Println(`You can copy executable files to any directory and start working with:
+nps.exe test|start|stop|restart|status
+now!`)
 	}
 	}
 }
 }
 func MkidrDirAll(path string, v ...string) {
 func MkidrDirAll(path string, v ...string) {

+ 8 - 0
lib/mux/conn.go

@@ -183,6 +183,10 @@ func (Self *ReceiveWindow) CalcSize() {
 			n = Self.bufQueue.Len()
 			n = Self.bufQueue.Len()
 		}
 		}
 		// set the minimal size
 		// set the minimal size
+		if n > common.MAXIMUM_WINDOW_SIZE {
+			n = common.MAXIMUM_WINDOW_SIZE
+		}
+		// set the maximum size
 		//logs.Warn("n", n)
 		//logs.Warn("n", n)
 		Self.maxSize = n
 		Self.maxSize = n
 		Self.count = -5
 		Self.count = -5
@@ -248,6 +252,10 @@ copyData:
 	l = 0
 	l = 0
 	Self.bw.EndRead()
 	Self.bw.EndRead()
 	Self.sendStatus(id)
 	Self.sendStatus(id)
+	if Self.off == uint32(Self.element.l) {
+		//logs.Warn("put the element end ", string(Self.element.buf[:15]))
+		common.WindowBuff.Put(Self.element.buf)
+	}
 	if pOff < len(p) && Self.element.part {
 	if pOff < len(p) && Self.element.part {
 		// element is a part of the segments, trying to fill up buf p
 		// element is a part of the segments, trying to fill up buf p
 		goto copyData
 		goto copyData

+ 15 - 2
lib/mux/mux.go

@@ -25,6 +25,7 @@ type Mux struct {
 	pingOk     int
 	pingOk     int
 	latency    float64
 	latency    float64
 	pingCh     chan []byte
 	pingCh     chan []byte
+	pingTimer  *time.Timer
 	connType   string
 	connType   string
 	writeQueue PriorityQueue
 	writeQueue PriorityQueue
 	bufCh      chan *bytes.Buffer
 	bufCh      chan *bytes.Buffer
@@ -42,6 +43,7 @@ func NewMux(c net.Conn, connType string) *Mux {
 		connType:  connType,
 		connType:  connType,
 		bufCh:     make(chan *bytes.Buffer),
 		bufCh:     make(chan *bytes.Buffer),
 		pingCh:    make(chan []byte),
 		pingCh:    make(chan []byte),
+		pingTimer: time.NewTimer(15 * time.Second),
 	}
 	}
 	m.writeQueue.New()
 	m.writeQueue.New()
 	//read session by flag
 	//read session by flag
@@ -119,6 +121,7 @@ func (s *Mux) packBuf() {
 			common.BuffPool.Put(buffer)
 			common.BuffPool.Put(buffer)
 			break
 			break
 		}
 		}
+		//logs.Warn(buffer.String())
 		select {
 		select {
 		case s.bufCh <- buffer:
 		case s.bufCh <- buffer:
 		case <-s.closeChan:
 		case <-s.closeChan:
@@ -153,7 +156,7 @@ func (s *Mux) ping() {
 		now, _ := time.Now().UTC().MarshalText()
 		now, _ := time.Now().UTC().MarshalText()
 		s.sendInfo(common.MUX_PING_FLAG, common.MUX_PING, now)
 		s.sendInfo(common.MUX_PING_FLAG, common.MUX_PING, now)
 		// send the ping flag and get the latency first
 		// send the ping flag and get the latency first
-		ticker := time.NewTicker(time.Second * 15)
+		ticker := time.NewTicker(time.Second * 5)
 		for {
 		for {
 			if s.IsClose {
 			if s.IsClose {
 				ticker.Stop()
 				ticker.Stop()
@@ -168,6 +171,10 @@ func (s *Mux) ping() {
 			}
 			}
 			now, _ := time.Now().UTC().MarshalText()
 			now, _ := time.Now().UTC().MarshalText()
 			s.sendInfo(common.MUX_PING_FLAG, common.MUX_PING, now)
 			s.sendInfo(common.MUX_PING_FLAG, common.MUX_PING, now)
+			if !s.pingTimer.Stop() {
+				<-s.pingTimer.C
+			}
+			s.pingTimer.Reset(15 * time.Second)
 			if s.pingOk > 10 && s.connType == "kcp" {
 			if s.pingOk > 10 && s.connType == "kcp" {
 				s.Close()
 				s.Close()
 				break
 				break
@@ -186,10 +193,15 @@ func (s *Mux) pingReturn() {
 			case data = <-s.pingCh:
 			case data = <-s.pingCh:
 			case <-s.closeChan:
 			case <-s.closeChan:
 				break
 				break
+			case <-s.pingTimer.C:
+				logs.Error("mux: ping time out")
+				s.Close()
+				break
 			}
 			}
 			_ = now.UnmarshalText(data)
 			_ = now.UnmarshalText(data)
 			s.latency = time.Now().UTC().Sub(now).Seconds() / 2
 			s.latency = time.Now().UTC().Sub(now).Seconds() / 2
-			//logs.Warn("latency", s.latency)
+			logs.Warn("latency", s.latency)
+			common.WindowBuff.Put(data)
 			if s.latency <= 0 {
 			if s.latency <= 0 {
 				logs.Warn("latency err", s.latency)
 				logs.Warn("latency err", s.latency)
 			}
 			}
@@ -218,6 +230,7 @@ func (s *Mux) readSession() {
 				continue
 				continue
 			case common.MUX_PING_FLAG: //ping
 			case common.MUX_PING_FLAG: //ping
 				s.sendInfo(common.MUX_PING_RETURN, common.MUX_PING, pack.Content)
 				s.sendInfo(common.MUX_PING_RETURN, common.MUX_PING, pack.Content)
+				common.WindowBuff.Put(pack.Content)
 				continue
 				continue
 			case common.MUX_PING_RETURN:
 			case common.MUX_PING_RETURN:
 				s.pingCh <- pack.Content
 				s.pingCh <- pack.Content

+ 52 - 0
lib/mux/mux_test.go

@@ -1,8 +1,11 @@
 package mux
 package mux
 
 
 import (
 import (
+	"bufio"
+	"fmt"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
+	"net/http/httputil"
 	_ "net/http/pprof"
 	_ "net/http/pprof"
 	"sync"
 	"sync"
 	"testing"
 	"testing"
@@ -37,6 +40,7 @@ func TestNewMux(t *testing.T) {
 			c2, err := net.Dial("tcp", "127.0.0.1:80")
 			c2, err := net.Dial("tcp", "127.0.0.1:80")
 			if err != nil {
 			if err != nil {
 				logs.Warn(err)
 				logs.Warn(err)
+				c.Close()
 				continue
 				continue
 			}
 			}
 			go func(c2 net.Conn, c net.Conn) {
 			go func(c2 net.Conn, c net.Conn) {
@@ -107,6 +111,9 @@ func TestNewMux(t *testing.T) {
 		}
 		}
 	}()
 	}()
 
 
+	time.Sleep(time.Second * 5)
+	//go test_request()
+
 	for {
 	for {
 		time.Sleep(time.Second * 5)
 		time.Sleep(time.Second * 5)
 	}
 	}
@@ -135,6 +142,51 @@ func client() {
 	}
 	}
 }
 }
 
 
+func test_request() {
+	conn, _ := net.Dial("tcp", "127.0.0.1:7777")
+	for {
+		conn.Write([]byte(`GET /videojs5/video.js HTTP/1.1
+Host: 127.0.0.1:7777
+Connection: keep-alive
+
+
+`))
+		r, err := http.ReadResponse(bufio.NewReader(conn), nil)
+		if err != nil {
+			logs.Warn("close by read response err", err)
+			break
+		}
+		logs.Warn("read response success", r)
+		b, err := httputil.DumpResponse(r, true)
+		if err != nil {
+			logs.Warn("close by dump response err", err)
+			break
+		}
+		fmt.Println(string(b[:20]), err)
+		time.Sleep(time.Second)
+	}
+}
+
+func test_raw() {
+	conn, _ := net.Dial("tcp", "127.0.0.1:7777")
+	for {
+		conn.Write([]byte(`GET /videojs5/test HTTP/1.1
+Host: 127.0.0.1:7777
+Connection: keep-alive
+
+
+`))
+		buf := make([]byte, 1000000)
+		n, err := conn.Read(buf)
+		if err != nil {
+			logs.Warn("close by read response err", err)
+			break
+		}
+		logs.Warn(n, string(buf[:50]), "\n--------------\n", string(buf[n-50:n]))
+		time.Sleep(time.Second)
+	}
+}
+
 func TestNewConn(t *testing.T) {
 func TestNewConn(t *testing.T) {
 	buf := common.GetBufPoolCopy()
 	buf := common.GetBufPoolCopy()
 	logs.Warn(len(buf), cap(buf))
 	logs.Warn(len(buf), cap(buf))

+ 28 - 11
lib/mux/queue.go

@@ -51,15 +51,23 @@ func (Self *PriorityQueue) New() {
 
 
 func (Self *PriorityQueue) Push(packager *common.MuxPackager) {
 func (Self *PriorityQueue) Push(packager *common.MuxPackager) {
 	Self.mutex.Lock()
 	Self.mutex.Lock()
-	if Self.popWait {
-		defer Self.allowPop()
-	}
-	if packager.Flag == common.MUX_CONN_CLOSE {
-		Self.insert(packager) // the close package may need priority,
-		// prevent wait too long to close
-	} else {
+	switch packager.Flag {
+	case common.MUX_PING_FLAG, common.MUX_PING_RETURN:
+		Self.list.PushFront(packager)
+	// the ping package need highest priority
+	// prevent ping calculation error
+	case common.MUX_CONN_CLOSE:
+		Self.insert(packager)
+	// the close package may need priority too, set second
+	// prevent wait too long to close conn
+	default:
 		Self.list.PushBack(packager)
 		Self.list.PushBack(packager)
 	}
 	}
+	if Self.popWait {
+		Self.mutex.Unlock()
+		Self.allowPop()
+		return
+	}
 	Self.mutex.Unlock()
 	Self.mutex.Unlock()
 	return
 	return
 }
 }
@@ -68,7 +76,14 @@ func (Self *PriorityQueue) insert(packager *common.MuxPackager) {
 	element := Self.list.Back()
 	element := Self.list.Back()
 	for {
 	for {
 		if element == nil { // PriorityQueue dose not have any of msg package with this close package id
 		if element == nil { // PriorityQueue dose not have any of msg package with this close package id
-			Self.list.PushFront(packager) // insert close package to first
+			element = Self.list.Front()
+			if element != nil {
+				Self.list.InsertAfter(packager, element)
+				// insert close package to second
+			} else {
+				Self.list.PushFront(packager)
+				// list is empty, push to front
+			}
 			break
 			break
 		}
 		}
 		if element.Value.(*common.MuxPackager).Flag == common.MUX_NEW_MSG &&
 		if element.Value.(*common.MuxPackager).Flag == common.MUX_NEW_MSG &&
@@ -136,11 +151,13 @@ func (Self *FIFOQueue) New() {
 
 
 func (Self *FIFOQueue) Push(element *ListElement) {
 func (Self *FIFOQueue) Push(element *ListElement) {
 	Self.mutex.Lock()
 	Self.mutex.Lock()
-	if Self.popWait {
-		defer Self.allowPop()
-	}
 	Self.list = append(Self.list, element)
 	Self.list = append(Self.list, element)
 	Self.length += uint32(element.l)
 	Self.length += uint32(element.l)
+	if Self.popWait {
+		Self.mutex.Unlock()
+		Self.allowPop()
+		return
+	}
 	Self.mutex.Unlock()
 	Self.mutex.Unlock()
 	return
 	return
 }
 }

+ 2 - 2
lib/version/version.go

@@ -1,8 +1,8 @@
 package version
 package version
 
 
-const VERSION = "0.23.2"
+const VERSION = "0.23.3"
 
 
 // Compulsory minimum version, Minimum downward compatibility to this version
 // Compulsory minimum version, Minimum downward compatibility to this version
 func GetVersion() string {
 func GetVersion() string {
-	return "0.21.0"
+	return "0.22.0"
 }
 }