Commit bc6d3d5d authored by Eric's avatar Eric

fix cpu 100% bug

parent 0ac28fda
...@@ -34,9 +34,6 @@ func newParser() *Parser { ...@@ -34,9 +34,6 @@ func newParser() *Parser {
// Parse 解析用户输入输出, 拦截过滤用户输入输出 // Parse 解析用户输入输出, 拦截过滤用户输入输出
type Parser struct { type Parser struct {
cmdBuf *bytes.Buffer
outputBuf *bytes.Buffer
userInputChan chan []byte userInputChan chan []byte
userOutputChan chan []byte userOutputChan chan []byte
srvInputChan chan []byte srvInputChan chan []byte
...@@ -61,9 +58,6 @@ type Parser struct { ...@@ -61,9 +58,6 @@ type Parser struct {
} }
func (p *Parser) initial() { func (p *Parser) initial() {
p.cmdBuf = new(bytes.Buffer)
p.outputBuf = new(bytes.Buffer)
p.once = new(sync.Once) p.once = new(sync.Once)
p.lock = new(sync.RWMutex) p.lock = new(sync.RWMutex)
...@@ -84,6 +78,8 @@ func (p *Parser) ParseStream() { ...@@ -84,6 +78,8 @@ func (p *Parser) ParseStream() {
close(p.userOutputChan) close(p.userOutputChan)
close(p.srvOutputChan) close(p.srvOutputChan)
close(p.cmdRecordChan) close(p.cmdRecordChan)
_ = p.cmdOutputParser.Close()
_ = p.cmdInputParser.Close()
logger.Debug("Parser parse stream routine done") logger.Debug("Parser parse stream routine done")
}() }()
for { for {
...@@ -96,7 +92,6 @@ func (p *Parser) ParseStream() { ...@@ -96,7 +92,6 @@ func (p *Parser) ParseStream() {
} }
b = p.ParseUserInput(b) b = p.ParseUserInput(b)
p.userOutputChan <- b p.userOutputChan <- b
case b, ok := <-p.srvInputChan: case b, ok := <-p.srvInputChan:
if !ok { if !ok {
return return
...@@ -121,7 +116,7 @@ func (p *Parser) parseInputState(b []byte) []byte { ...@@ -121,7 +116,7 @@ func (p *Parser) parseInputState(b []byte) []byte {
p.parseCmdInput() p.parseCmdInput()
if cmd, ok := p.IsCommandForbidden(); !ok { if cmd, ok := p.IsCommandForbidden(); !ok {
fbdMsg := utils.WrapperWarn(fmt.Sprintf(i18n.T("Command `%s` is forbidden"), cmd)) fbdMsg := utils.WrapperWarn(fmt.Sprintf(i18n.T("Command `%s` is forbidden"), cmd))
p.outputBuf.WriteString(fbdMsg) p.cmdOutputParser.WriteData([]byte(fbdMsg))
p.srvOutputChan <- []byte("\r\n" + fbdMsg) p.srvOutputChan <- []byte("\r\n" + fbdMsg)
return []byte{utils.CharCleanLine, '\r'} return []byte{utils.CharCleanLine, '\r'}
} }
...@@ -138,16 +133,12 @@ func (p *Parser) parseInputState(b []byte) []byte { ...@@ -138,16 +133,12 @@ func (p *Parser) parseInputState(b []byte) []byte {
// parseCmdInput 解析命令的输入 // parseCmdInput 解析命令的输入
func (p *Parser) parseCmdInput() { func (p *Parser) parseCmdInput() {
data := p.cmdBuf.Bytes() p.command = p.cmdInputParser.Parse()
p.command = p.cmdInputParser.Parse(data)
p.cmdBuf.Reset()
} }
// parseCmdOutput 解析命令输出 // parseCmdOutput 解析命令输出
func (p *Parser) parseCmdOutput() { func (p *Parser) parseCmdOutput() {
data := p.outputBuf.Bytes() p.output = p.cmdOutputParser.Parse()
p.output = p.cmdOutputParser.Parse(data)
p.outputBuf.Reset()
} }
// ParseUserInput 解析用户的输入 // ParseUserInput 解析用户的输入
...@@ -206,14 +197,12 @@ func (p *Parser) splitCmdStream(b []byte) { ...@@ -206,14 +197,12 @@ func (p *Parser) splitCmdStream(b []byte) {
return return
} }
if p.inputState { if p.inputState {
p.cmdBuf.Write(b) p.cmdInputParser.WriteData(b)
return return
} }
// outputBuff 最大存储1024, 否则可能撑爆内存 // outputBuff 最大存储1024, 否则可能撑爆内存
// 如果最后一个字符不是ascii, 可以截断了某个中文字符的一部分,为了安全继续添加 // 如果最后一个字符不是ascii, 可以截断了某个中文字符的一部分,为了安全继续添加
if p.outputBuf.Len() < 1024 || p.outputBuf.Bytes()[p.outputBuf.Len()-1] > 128 { p.cmdOutputParser.WriteData(b)
p.outputBuf.Write(b)
}
} }
// ParseServerOutput 解析服务器输出 // ParseServerOutput 解析服务器输出
......
package proxy package proxy
import ( import (
"bytes" "io"
"regexp" "regexp"
"strings" "strings"
"sync"
"github.com/jumpserver/koko/pkg/logger"
"github.com/jumpserver/koko/pkg/utils" "github.com/jumpserver/koko/pkg/utils"
) )
...@@ -18,17 +20,56 @@ func NewCmdParser() *CmdParser { ...@@ -18,17 +20,56 @@ func NewCmdParser() *CmdParser {
type CmdParser struct { type CmdParser struct {
term *utils.Terminal term *utils.Terminal
buf *bytes.Buffer reader io.ReadCloser
writer io.WriteCloser
currentLines []string
lock *sync.Mutex
maxLength int
currentLength int
}
func (cp *CmdParser) WriteData(p []byte) (int,error){
return cp.writer.Write(p)
}
func (cp *CmdParser) Write (p []byte) (int,error){
return len(p),nil
}
func (cp *CmdParser) Read(p []byte)(int,error){
return cp.reader.Read(p)
} }
func (cp *CmdParser) Reset() { func (cp *CmdParser) Close() error{
cp.buf.Reset() return cp.writer.Close()
} }
func (cp *CmdParser) initial() { func (cp *CmdParser) initial() {
cp.buf = new(bytes.Buffer) cp.reader,cp.writer = io.Pipe()
cp.term = utils.NewTerminal(cp.buf, "") cp.currentLines = make([]string,0)
cp.lock = new(sync.Mutex)
cp.maxLength = 1024
cp.currentLength = 0
cp.term = utils.NewTerminal(cp, "")
cp.term.SetEcho(false) cp.term.SetEcho(false)
go func() {
logger.Debug("command Parser start")
defer logger.Debug("command Parser close")
for {
line, err := cp.term.ReadLine()
if err != nil{
break
}
cp.lock.Lock()
cp.currentLength += len(line)
if cp.currentLength < cp.maxLength {
cp.currentLines = append(cp.currentLines,line)
}
cp.lock.Unlock()
}
}()
} }
func (cp *CmdParser) parsePS1(s string) string { func (cp *CmdParser) parsePS1(s string) string {
...@@ -36,12 +77,13 @@ func (cp *CmdParser) parsePS1(s string) string { ...@@ -36,12 +77,13 @@ func (cp *CmdParser) parsePS1(s string) string {
} }
// Parse 解析命令或输出 // Parse 解析命令或输出
func (cp *CmdParser) Parse(b []byte) string { func (cp *CmdParser) Parse() string {
cp.buf.Write(b) cp.writer.Write([]byte("\r"))
cp.buf.WriteString("\r") cp.lock.Lock()
lines, _ := cp.term.ReadLines() defer cp.lock.Unlock()
cp.Reset() output := strings.TrimSpace(strings.Join(cp.currentLines, "\r\n"))
output := strings.TrimSpace(strings.Join(lines, "\r\n"))
output = cp.parsePS1(output) output = cp.parsePS1(output)
cp.currentLines = make([]string,0)
cp.currentLength = 0
return output return output
} }
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"io" "io"
"strconv" "strconv"
"sync" "sync"
"time"
"unicode/utf8" "unicode/utf8"
) )
...@@ -796,7 +795,6 @@ func (t *Terminal) readLine() (line string, err error) { ...@@ -796,7 +795,6 @@ func (t *Terminal) readLine() (line string, err error) {
for !lineOk { for !lineOk {
var key rune var key rune
key, rest = bytesToKey(rest, t.pasteActive) key, rest = bytesToKey(rest, t.pasteActive)
time.Sleep(10 * time.Millisecond)
if key == utf8.RuneError { if key == utf8.RuneError {
break break
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment