Signal Zlib encode failure and fall back to Raw

This commit is contained in:
Viktor Liu
2026-05-22 12:06:52 +02:00
parent 0f03c612d1
commit 030c57150f
2 changed files with 18 additions and 9 deletions
+4 -4
View File
@@ -266,7 +266,7 @@ func encodeRawRect(img *image.RGBA, pf clientPixelFormat, x, y, w, h int) []byte
// encoding. The zlib stream is continuous for the entire VNC session: the // encoding. The zlib stream is continuous for the entire VNC session: the
// client keeps a single inflate context and reuses it across rects. The // client keeps a single inflate context and reuses it across rects. The
// returned buffer includes the 4-byte FramebufferUpdate header. // returned buffer includes the 4-byte FramebufferUpdate header.
func encodeZlibRect(img *image.RGBA, pf clientPixelFormat, x, y, w, h int, z *zlibState) []byte { func encodeZlibRect(img *image.RGBA, pf clientPixelFormat, x, y, w, h int, z *zlibState) ([]byte, bool) {
zw, zbuf := z.w, z.buf zw, zbuf := z.w, z.buf
zbuf.Reset() zbuf.Reset()
@@ -280,12 +280,12 @@ func encodeZlibRect(img *image.RGBA, pf clientPixelFormat, x, y, w, h int, z *zl
for row := 0; row < h; row++ { for row := 0; row < h; row++ {
if _, err := zw.Write(scratch[row*rowBytes : (row+1)*rowBytes]); err != nil { if _, err := zw.Write(scratch[row*rowBytes : (row+1)*rowBytes]); err != nil {
log.Debugf("zlib write row %d: %v", row, err) log.Debugf("zlib write row %d: %v", row, err)
return nil return nil, false
} }
} }
if err := zw.Flush(); err != nil { if err := zw.Flush(); err != nil {
log.Debugf("zlib flush: %v", err) log.Debugf("zlib flush: %v", err)
return nil return nil, false
} }
compressed := zbuf.Bytes() compressed := zbuf.Bytes()
@@ -299,7 +299,7 @@ func encodeZlibRect(img *image.RGBA, pf clientPixelFormat, x, y, w, h int, z *zl
binary.BigEndian.PutUint32(buf[12:16], uint32(encZlib)) binary.BigEndian.PutUint32(buf[12:16], uint32(encZlib))
binary.BigEndian.PutUint32(buf[16:20], uint32(len(compressed))) binary.BigEndian.PutUint32(buf[16:20], uint32(len(compressed)))
copy(buf[20:], compressed) copy(buf[20:], compressed)
return buf return buf, true
} }
// encodeHextileSolidRect emits a Hextile-encoded rectangle whose every // encodeHextileSolidRect emits a Hextile-encoded rectangle whose every
+14 -5
View File
@@ -450,11 +450,18 @@ func (s *session) sendFullUpdate(img *image.RGBA) error {
rectBuf = encodeTightRect(img, pf, 0, 0, w, h, tight) rectBuf = encodeTightRect(img, pf, 0, 0, w, h, tight)
case useZlib && zlib != nil: case useZlib && zlib != nil:
// encodeZlibRect bakes in its own FBU header; reuse it for the // encodeZlibRect bakes in its own FBU header; reuse it for the
// single-rect path when there is no cursor to prepend. // single-rect path when there is no cursor to prepend. Fall back
if cursorRect == nil { // to Raw if the compressor errors out.
return s.writeFramed(encodeZlibRect(img, pf, 0, 0, w, h, zlib)) if zb, ok := encodeZlibRect(img, pf, 0, 0, w, h, zlib); ok {
if cursorRect == nil {
return s.writeFramed(zb)
}
rectBuf = zb[4:]
} else if cursorRect == nil {
return s.writeFramed(encodeRawRect(img, pf, 0, 0, w, h))
} else {
rectBuf = encodeRawRect(img, pf, 0, 0, w, h)[4:]
} }
rectBuf = encodeZlibRect(img, pf, 0, 0, w, h, zlib)[4:]
default: default:
if cursorRect == nil { if cursorRect == nil {
return s.writeFramed(encodeRawRect(img, pf, 0, 0, w, h)) return s.writeFramed(encodeRawRect(img, pf, 0, 0, w, h))
@@ -558,7 +565,9 @@ func (s *session) encodeTile(img *image.RGBA, x, y, w, h int) []byte {
return encodeTightRect(img, pf, x, y, w, h, tight) return encodeTightRect(img, pf, x, y, w, h, tight)
} }
if useZlib && zlib != nil { if useZlib && zlib != nil {
return encodeZlibRect(img, pf, x, y, w, h, zlib)[4:] if zb, ok := encodeZlibRect(img, pf, x, y, w, h, zlib); ok {
return zb[4:]
}
} }
return encodeRawRect(img, pf, x, y, w, h)[4:] return encodeRawRect(img, pf, x, y, w, h)[4:]
} }