Skip to content

Commit

Permalink
#3592 remove zlib compression
Browse files Browse the repository at this point in the history
  • Loading branch information
totaam committed Jul 26, 2023
1 parent 1a217ab commit 1c14d1a
Show file tree
Hide file tree
Showing 13 changed files with 23 additions and 48 deletions.
3 changes: 1 addition & 2 deletions fs/etc/xpra/conf.d/10_network.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ lock = auto
# Compressors:
#compressors = all
#compressors = none
#compressors = zlib
compressors = none, lz4, zlib, brotli
compressors = none, lz4, brotli

# Default compression (0 to 9):
compression_level = 1
Expand Down
3 changes: 0 additions & 3 deletions fs/share/man/man1/xpra.1
Original file line number Diff line number Diff line change
Expand Up @@ -1311,9 +1311,6 @@ over the network.
With the \fBlz4\fP and \fBlzo\fP compressors,
there are only two possible values:
0 (meaning no compression) and 1 (compression enabled).
The \fBzlib\fP compressor supports values between 0
(meaning no compression) and 9, inclusive. It should only be used
when \fBlz4\fP and \fBlzo\fP are not available.

This compression is not used on pixel data (except
when using the \fBrgb\fP encoding).
Expand Down
4 changes: 2 additions & 2 deletions tests/unittests/unit/net/compression_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TestCompression(unittest.TestCase):

def test_main(self):
compression.init_all()
assert compression.use("zlib")
assert compression.use("lz4")
assert compression.get_compression_caps()
assert compression.get_enabled_compressors()
for x in compression.get_enabled_compressors():
Expand Down Expand Up @@ -57,7 +57,7 @@ def test_compressed_wrapper(self):
r = compression.compressed_wrapper("test", b"a"*(compression.MIN_COMPRESS_SIZE+1))
if not r.datatype.startswith("raw"):
raise Exception(f"should not be able to use the wrapper without enabling a compressor, but got {r!r}")
for x in ("lz4", "brotli", "zlib", "none"):
for x in ("lz4", "brotli", "none"):
if not compression.use(x):
continue
kwargs = {x : True}
Expand Down
2 changes: 1 addition & 1 deletion tests/unittests/unit/net/protocol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def check_failed():

def test_encoders_and_compressors(self):
for encoder in ("rencodeplus", ):
for compressor in ("lz4", "zlib"):
for compressor in ("lz4", ):
p = self.make_memory_protocol()
p.enable_encoder(encoder)
p.enable_compressor(compressor)
Expand Down
1 change: 0 additions & 1 deletion tests/xpra/codecs/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ def main(argv):
"quality" : quality,
"speed" : speed,
"rgb_formats" : ("BGRX", "BGRA", "RGBA", "RGBX", "RGB", "BGR"),
"zlib" : True,
"lz4" : True,
"alpha" : True,
}
Expand Down
1 change: 0 additions & 1 deletion xpra/audio/src.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ def on_new_sample(self, _bus) -> int:
def _emit_buffer(self, data, metadata) -> int:
if self.stream_compressor and data:
cdata = compressed_wrapper("audio", data, level=9, can_inline=True,
zlib=False,
lz4=self.stream_compressor=="lz4")
if len(cdata)<len(data)*90//100:
log("compressed using %s from %i bytes down to %i bytes", self.stream_compressor, len(data), len(cdata))
Expand Down
3 changes: 1 addition & 2 deletions xpra/client/base/client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ def compressed_wrapper(self, datatype, data, level=5, **kwargs) -> compression.C
#brotli is not enabled by default as a generic compressor
#but callers may choose to enable it via kwargs:
for algo, defval in {
"zlib" : True,
"lz4" : True,
"brotli" : False,
}.items():
Expand Down Expand Up @@ -1117,7 +1116,7 @@ def parse_server_capabilities(self, c : typedict) -> bool:
log.info(f"server capabilities rejected by {bc}")
return False
self.server_client_shutdown = c.boolget("client-shutdown", True)
self.server_compressors = c.strtupleget("compressors", ("zlib",))
self.server_compressors = c.strtupleget("compressors", )
return True

def parse_network_capabilities(self, caps : typedict) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion xpra/client/base/stub_client_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def compressed_wrapper(self, datatype, data, level=5, **kwargs) -> Compressed:
"""
Dummy utility method for compressing data.
Actual client implementations will provide compression
based on the client and server capabilities (lz4, zlib).
based on the client and server capabilities (ie: lz4, brotli).
subclasses should override this method.
"""
assert level>=0
Expand Down
26 changes: 6 additions & 20 deletions xpra/net/compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
from xpra.common import MIN_COMPRESS_SIZE, MAX_DECOMPRESSED_SIZE


# all the compressors we know about, in the best compatibility order:
# all the compressors we know about:
ALL_COMPRESSORS : Tuple[str, ...] = ("lz4", "zlib", "brotli", "none")
# the compressors we may want to use, in the best compatibility order:
TRY_COMPRESSORS : Tuple[str, ...] = ("lz4", "brotli", "none")
# order for performance:
PERFORMANCE_ORDER : Tuple[str, ...] = ("none", "lz4", "zlib", "brotli")
# require compression (disallow 'none'):
Expand Down Expand Up @@ -55,22 +57,6 @@ def brotli_compress_shim(packet, level):
return level | BROTLI_FLAG, brotli_compress(packet, quality=level)
return Compression("brotli", brotli_version, brotli_compress_shim, brotli_decompress)

def init_zlib() -> Compression:
#pylint: disable=import-outside-toplevel
import zlib
from xpra.net.protocol.header import ZLIB_FLAG
def zlib_compress(packet, level):
level = min(9, max(1, level))
if not isinstance(packet, (bytes, bytearray, memoryview)):
packet = bytes(str(packet), 'UTF-8')
return level + ZLIB_FLAG, zlib.compress(packet, level)
def zlib_decompress(data):
d = zlib.decompressobj()
v = d.decompress(data, MAX_DECOMPRESSED_SIZE)
assert not d.unconsumed_tail, "not all data was decompressed"
return v
return Compression("zlib", zlib.__version__, zlib_compress, zlib_decompress) # type: ignore[attr-defined]

def init_none() -> Compression:
def nocompress(packet, _level):
if not isinstance(packet, bytes):
Expand Down Expand Up @@ -101,7 +87,7 @@ def init_compressors(*names) -> None:
logger(f"no {x}", exc_info=True)

def init_all() -> None:
init_compressors(*(list(ALL_COMPRESSORS)+["none"]))
init_compressors(*(list(TRY_COMPRESSORS)+["none"]))


def use(compressor) -> bool:
Expand All @@ -110,7 +96,7 @@ def use(compressor) -> bool:

def get_compression_caps(full_info : int=1) -> Dict[str,Any]:
caps : Dict[str,Any] = {}
for x in ALL_COMPRESSORS:
for x in TRY_COMPRESSORS:
c = COMPRESSION.get(x)
if c is None:
continue
Expand All @@ -120,7 +106,7 @@ def get_compression_caps(full_info : int=1) -> Dict[str,Any]:
ccaps[""] = True
return caps

def get_enabled_compressors(order=ALL_COMPRESSORS) -> Tuple[str,...]:
def get_enabled_compressors(order=TRY_COMPRESSORS) -> Tuple[str,...]:
return tuple(x for x in order if x in COMPRESSION)

def get_compressor(name) -> Callable:
Expand Down
4 changes: 2 additions & 2 deletions xpra/net/protocol/socket_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ def enable_compressor_from_caps(self, caps:typedict) -> None:
opts = compression.get_enabled_compressors(order=compression.PERFORMANCE_ORDER)
compressors = caps.strtupleget("compressors")
log(f"enable_compressor_from_caps(..) options={opts}, compressors from caps={compressors}")
for c in opts: #ie: [zlib, lz4]
for c in opts: #ie: ["lz4", "none"]
if c=="none":
continue
if c in compressors or caps.boolget(c):
Expand Down Expand Up @@ -538,7 +538,7 @@ def encode(self, packet_in : PacketType) -> List[NetPacketType]:
ie: ["blah", [large binary data], "hello", 200]
may get converted to:
[
(1, compression_level, [large binary data now zlib compressed]),
(1, compression_level, [large binary data now lz4 compressed]),
(0, 0, rencoded(["blah", '', "hello", 200]))
]
"""
Expand Down
3 changes: 1 addition & 2 deletions xpra/server/proxy/proxy_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ def number(k, v):
OPTION_WHITELIST : Dict[str,Callable] = {
"compression_level" : number,
"lz4" : parse_bool,
"zlib" : parse_bool,
"rencodeplus" : parse_bool,
"yaml" : parse_bool,
}
Expand Down Expand Up @@ -393,7 +392,7 @@ def _packet_recompress(self, packet : PacketType, index:int, name:str) -> Packet
if len(data)<MIN_COMPRESS_SIZE:
return packet
#this is ugly and not generic!
kw = dict((k, self.caps.boolget(k)) for k in ("zlib", "lz4"))
kw = {"lz4" : self.caps.boolget("lz4")}
return self.replace_packet_item(packet, index, compressed_wrapper(name, data, can_inline=False, **kw))


Expand Down
4 changes: 2 additions & 2 deletions xpra/server/source/client_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ def may_notify(self, *args, **kwargs):


def compressed_wrapper(self, datatype, data, **kwargs):
#set compression flags based on self.zlib and self.lz4:
kw = dict((k, getattr(self, k, False)) for k in ("zlib", "lz4"))
#set compression flags based on self.lz4:
kw = {"lz4" : getattr(self, "lz4", False)}
kw.update(kwargs)
return compressed_wrapper(datatype, data, can_inline=False, **kw)

Expand Down
15 changes: 6 additions & 9 deletions xpra/server/source/encodings.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ def init_state(self) -> None:
self.default_encoding_options = typedict()
self.auto_refresh_delay : int = 0

self.zlib = True
self.lz4 = use("lz4")

#for managing the recalculate_delays work:
Expand Down Expand Up @@ -249,11 +248,9 @@ def parse_batch_int(value, varname):
return v

#general features:
self.zlib = c.boolget("zlib", True)
self.lz4 = c.boolget("lz4", False) and use("lz4")
self.brotli = c.boolget("brotli", False) and use("brotli")
log("compressors: zlib=%s, lz4=%s, brotli=%s",
self.zlib, self.lz4, self.brotli)
log("compressors: lz4=%s, brotli=%s", self.lz4, self.brotli)

delay = batch_config.START_DELAY
dbc = self.default_batch_config
Expand Down Expand Up @@ -292,15 +289,15 @@ def parse_encoding_caps(self, c:typedict) -> None:
#encoding options (filter):
#1: these properties are special cased here because we
#defined their name before the "encoding." prefix convention,
#or because we want to pass default values (zlib/lz4):
#or because we want to pass default values (ie: lz4):
for k,ek in {"initial_quality" : "initial_quality",
"quality" : "quality",
}.items():
if k in c:
self.encoding_options[ek] = c.intget(k)
for k,ek in {"zlib" : "rgb_zlib",
"lz4" : "rgb_lz4",
}.items():
for k,ek in {
"lz4" : "rgb_lz4",
}.items():
if k in c:
self.encoding_options[ek] = c.boolget(k)
#2: standardized encoding options:
Expand All @@ -312,7 +309,7 @@ def parse_encoding_caps(self, c:typedict) -> None:
elif k.startswith("encoding."):
stripped_k = k[len("encoding."):]
if stripped_k in ("transparency",
"rgb_zlib", "rgb_lz4",
"rgb_lz4",
):
v = c.boolget(k)
elif stripped_k in ("initial_quality", "initial_speed",
Expand Down

0 comments on commit 1c14d1a

Please sign in to comment.