mirror of https://github.com/jetkvm/kvm.git
Compare commits
1 Commits
96579685ec
...
93133f6bec
| Author | SHA1 | Date |
|---|---|---|
|
|
93133f6bec |
|
|
@ -355,45 +355,14 @@ func (b *ConsoleBroker) handleRX(data []byte) {
|
||||||
if b.sink == nil || len(data) == 0 {
|
if b.sink == nil || len(data) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we’re mid TX line, end it before RX
|
|
||||||
if b.txLineActive {
|
|
||||||
b.emitToTerminal(b.lineSep())
|
|
||||||
b.txLineActive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
text := normalize(data, b.norm)
|
text := normalize(data, b.norm)
|
||||||
if text == "" {
|
if text != "" {
|
||||||
return
|
scopedLogger.Info().Msg("Emitting RX data to sink")
|
||||||
|
b.emitToTerminal(fmt.Sprintf("%s: %s", b.labelRX, text))
|
||||||
}
|
}
|
||||||
|
|
||||||
scopedLogger.Info().Msg("Emitting RX data to sink (with per-line prefixes)")
|
last := data[len(data)-1]
|
||||||
|
b.rxAtLineEnd = (last == '\r' || last == '\n')
|
||||||
// Prefix every line, regardless of how the EOLs look
|
|
||||||
lines := splitAfterAnyEOL(text, b.norm.CRLF)
|
|
||||||
|
|
||||||
// Start from the broker's current RX line state
|
|
||||||
atLineEnd := b.rxAtLineEnd
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
if line == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if atLineEnd {
|
|
||||||
// New physical line -> prefix with RX:
|
|
||||||
b.emitToTerminal(fmt.Sprintf("%s: %s", b.labelRX, line))
|
|
||||||
} else {
|
|
||||||
// Continuation of previous RX line -> no extra RX: prefix
|
|
||||||
b.emitToTerminal(line)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update line-end state based on this piece
|
|
||||||
atLineEnd = endsWithEOL(line, b.norm.CRLF)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Persist state for next RX chunk
|
|
||||||
b.rxAtLineEnd = atLineEnd
|
|
||||||
|
|
||||||
if b.pendingTX != nil && b.rxAtLineEnd {
|
if b.pendingTX != nil && b.rxAtLineEnd {
|
||||||
b.flushPendingTX()
|
b.flushPendingTX()
|
||||||
|
|
@ -458,8 +427,6 @@ func (b *ConsoleBroker) lineSep() string {
|
||||||
switch b.norm.CRLF {
|
switch b.norm.CRLF {
|
||||||
case CRLF_CRLF:
|
case CRLF_CRLF:
|
||||||
return "\r\n"
|
return "\r\n"
|
||||||
case CRLF_LFCR:
|
|
||||||
return "\n\r"
|
|
||||||
case CRLF_CR:
|
case CRLF_CR:
|
||||||
return "\r"
|
return "\r"
|
||||||
case CRLF_LF:
|
case CRLF_LF:
|
||||||
|
|
@ -469,69 +436,6 @@ func (b *ConsoleBroker) lineSep() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// splitAfterAnyEOL splits text into lines keeping the EOL with each piece.
|
|
||||||
// For CRLFAsIs it treats \r, \n, \r\n, and \n\r as EOLs.
|
|
||||||
// For other modes it uses the normalized separator.
|
|
||||||
func splitAfterAnyEOL(text string, mode CRLFMode) []string {
|
|
||||||
if text == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fast path for normalized modes
|
|
||||||
switch mode {
|
|
||||||
case CRLF_LF:
|
|
||||||
return strings.SplitAfter(text, "\n")
|
|
||||||
case CRLF_CR:
|
|
||||||
return strings.SplitAfter(text, "\r")
|
|
||||||
case CRLF_CRLF:
|
|
||||||
return strings.SplitAfter(text, "\r\n")
|
|
||||||
case CRLF_LFCR:
|
|
||||||
return strings.SplitAfter(text, "\n\r")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CRLFAsIs: scan bytes and treat \r, \n, \r\n, \n\r as one boundary
|
|
||||||
b := []byte(text)
|
|
||||||
var parts []string
|
|
||||||
start := 0
|
|
||||||
for i := 0; i < len(b); i++ {
|
|
||||||
if b[i] == '\r' || b[i] == '\n' {
|
|
||||||
j := i + 1
|
|
||||||
// coalesce pair if the next is the "other" newline
|
|
||||||
if j < len(b) && ((b[i] == '\r' && b[j] == '\n') || (b[i] == '\n' && b[j] == '\r')) {
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
parts = append(parts, string(b[start:j]))
|
|
||||||
start = j
|
|
||||||
i = j - 1 // advance past the EOL (or pair)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if start < len(b) {
|
|
||||||
parts = append(parts, string(b[start:]))
|
|
||||||
}
|
|
||||||
return parts
|
|
||||||
}
|
|
||||||
|
|
||||||
func endsWithEOL(s string, mode CRLFMode) bool {
|
|
||||||
if s == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch mode {
|
|
||||||
case CRLF_CRLF:
|
|
||||||
return strings.HasSuffix(s, "\r\n")
|
|
||||||
case CRLF_LFCR:
|
|
||||||
return strings.HasSuffix(s, "\n\r")
|
|
||||||
case CRLF_LF:
|
|
||||||
return strings.HasSuffix(s, "\n")
|
|
||||||
case CRLF_CR:
|
|
||||||
return strings.HasSuffix(s, "\r")
|
|
||||||
default: // AsIs: any of \r, \n, \r\n, \n\r
|
|
||||||
return strings.HasSuffix(s, "\r\n") ||
|
|
||||||
strings.HasSuffix(s, "\n\r") ||
|
|
||||||
strings.HasSuffix(s, "\n") ||
|
|
||||||
strings.HasSuffix(s, "\r")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *ConsoleBroker) emitToTerminal(s string) {
|
func (b *ConsoleBroker) emitToTerminal(s string) {
|
||||||
if b.sink == nil || s == "" {
|
if b.sink == nil || s == "" {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue