From 01dc73be80d081732dee6e8dc2ecc0574b679149 Mon Sep 17 00:00:00 2001 From: totaam Date: Sat, 25 Feb 2023 19:37:29 +0700 Subject: [PATCH] #3772 add 'rencodeplus' --- .gitignore | 1 + src/etc/xpra/conf.d/10_network.conf.in | 2 +- src/setup.py | 13 ++++++- xpra/net/header.py | 1 + xpra/net/packet_encoding.py | 49 ++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index e850515e8a..0e644a5b34 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,7 @@ tests/unittests/test-file* /xpra/gtk_common/gtk3/gdk_bindings.c /xpra/net/vsock.c /xpra/net/bencode/cython_bencode.c +/xpra/net/rencodeplus/rencodeplus.c /xpra/platform/darwin/gdk3_bindings.c /xpra/platform/win32/propsys.cpp /xpra/platform/xposix/netdev_query.c diff --git a/src/etc/xpra/conf.d/10_network.conf.in b/src/etc/xpra/conf.d/10_network.conf.in index 2eeae9ded8..daf6993e10 100644 --- a/src/etc/xpra/conf.d/10_network.conf.in +++ b/src/etc/xpra/conf.d/10_network.conf.in @@ -45,7 +45,7 @@ compression_level = 1 # Packet encoders (at least one is required): #packet-encoders = bencode #packet-encoders = all -packet-encoders = rencode, bencode, yaml +packet-encoders = rencode, rencodeplus, bencode, yaml # Socket directories (may be specified more than once): #socket-dirs = /tmp diff --git a/src/setup.py b/src/setup.py index 637d3a5265..7e49dc447c 100755 --- a/src/setup.py +++ b/src/setup.py @@ -183,6 +183,7 @@ def is_RH(): vsock_ENABLED = LINUX and os.path.exists("/usr/include/linux/vm_sockets.h") bencode_ENABLED = DEFAULT cython_bencode_ENABLED = DEFAULT +rencodeplus_ENABLED = DEFAULT clipboard_ENABLED = DEFAULT Xdummy_ENABLED = None if POSIX else False #None means auto-detect Xdummy_wrapper_ENABLED = None if POSIX else False #None means auto-detect @@ -241,7 +242,8 @@ def is_RH(): "nvjpeg", "dec_avcodec2", "csc_swscale", "csc_libyuv", - "bencode", "cython_bencode", "vsock", "netdev", "mdns", + "bencode", "cython_bencode", "rencodeplus", + "vsock", "netdev", "mdns", "clipboard", "scripts", "server", "client", "dbus", "x11", "xinput", "uinput", "sd_listen", @@ -946,6 +948,7 @@ def clean(): "xpra/platform/xposix/sd_listen.c", "xpra/platform/xposix/netdev_query.c", "xpra/net/bencode/cython_bencode.c", + "xpra/net/rencodeplus/rencodeplus.c", "xpra/net/vsock.c", "xpra/buffers/membuf.c", "xpra/codecs/vpx/encoder.c", @@ -2457,6 +2460,14 @@ def get_nvcc_version(command): ["xpra/net/bencode/cython_bencode.pyx"], **bencode_pkgconfig)) +toggle_packages(rencodeplus_ENABLED, "xpra.net.rencodeplus") +toggle_packages(rencodeplus_ENABLED and cython_bencode_ENABLED, "xpra.net.rencodeplus.rencodeplus") +if rencodeplus_ENABLED: + rencodeplus_pkgconfig = pkgconfig(optimize=3) + cython_add(Extension("xpra.net.rencodeplus.rencodeplus", + ["xpra/net/rencodeplus/rencodeplus.pyx"], + **rencodeplus_pkgconfig)) + if netdev_ENABLED: netdev_pkgconfig = pkgconfig() cython_add(Extension("xpra.platform.xposix.netdev_query", diff --git a/xpra/net/header.py b/xpra/net/header.py index 23a89b1e75..b6795c8589 100644 --- a/xpra/net/header.py +++ b/xpra/net/header.py @@ -15,6 +15,7 @@ FLAGS_RENCODE = 0x1 FLAGS_CIPHER = 0x2 FLAGS_YAML = 0x4 +FLAGS_RENCODEPLUS = 0x10 #compression flags are carried in the "level" field, #the low bits contain the compression level, the high bits the compression algo: diff --git a/xpra/net/packet_encoding.py b/xpra/net/packet_encoding.py index 5cf587f33e..c67c9a3930 100644 --- a/xpra/net/packet_encoding.py +++ b/xpra/net/packet_encoding.py @@ -1,23 +1,40 @@ #!/usr/bin/env python # This file is part of Xpra. -# Copyright (C) 2011-2019 Antoine Martin +# Copyright (C) 2011-2023 Antoine Martin # Copyright (C) 2008, 2009, 2010 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from xpra.log import Logger from xpra.os_util import PYTHON3 -from xpra.net.header import FLAGS_RENCODE, FLAGS_YAML, FLAGS_BENCODE +from xpra.net.header import FLAGS_RENCODE, FLAGS_YAML, FLAGS_BENCODE, FLAGS_RENCODEPLUS from xpra.util import envbool log = Logger("network", "protocol") #those are also modified from the command line switch: use_rencode = envbool("XPRA_USE_RENCODER", True) +use_rencodeplus = envbool("XPRA_USE_RENCODEPLUS", True) use_bencode = envbool("XPRA_USE_BENCODER", True) use_yaml = envbool("XPRA_USE_YAML", True) +has_rencodeplus = False +rencodeplus_dumps, rencodeplus_loads, rencodeplus_version = None, None, None +def init_rencodeplus(): + global use_rencodeplus, has_rencodeplus, rencodeplus_dumps, rencodeplus_loads, rencodeplus_version + try: + from xpra.net.rencodeplus import rencodeplus #pylint: disable=no-name-in-module + rencodeplus_dumps = rencodeplus.dumps + rencodeplus_loads = rencodeplus.loads + rencodeplus_version = rencodeplus.__version__ + has_rencodeplus = True + except ImportError: + return + use_rencodeplus = has_rencodeplus and use_rencodeplus + log.warn("init_rencodeplus() use_rencodeplus=%s", use_rencodeplus) + + has_rencode = None rencode_dumps, rencode_loads, rencode_version = None, None, None def init_rencode(): @@ -92,11 +109,15 @@ def yaml_encode_py3(v): log("packet encoding: has_yaml=%s, use_yaml=%s, version=%s", has_yaml, use_yaml, yaml_version) def init(): + init_rencodeplus() init_rencode() init_bencode() init_yaml() init() +def do_rencodeplus(data): + return rencodeplus_dumps(data), FLAGS_RENCODEPLUS + def do_bencode(data): return bencode(data), FLAGS_BENCODE @@ -108,6 +129,10 @@ def do_yaml(data): def get_packet_encoding_caps(): + rp = {"" : use_rencodeplus} + if has_rencodeplus: + assert rencode_version is not None + rp["version"] = rencodeplus_version r = {"" : use_rencode} if has_rencode: assert rencode_version is not None @@ -121,6 +146,7 @@ def get_packet_encoding_caps(): assert yaml_version is not None y["version"] = yaml_version return { + "rencodeplus" : rp, "rencode" : r, "bencode" : b, "yaml" : y, @@ -128,12 +154,13 @@ def get_packet_encoding_caps(): #all the encoders we know about, in best compatibility order: -ALL_ENCODERS = ("rencode", "bencode", "yaml") +ALL_ENCODERS = ("rencode", "bencode", "rencodeplus", "yaml") #order for performance: -PERFORMANCE_ORDER = ["rencode", "bencode", "yaml"] +PERFORMANCE_ORDER = ["rencodeplus", "rencode", "bencode", "yaml"] _ENCODERS = { + "rencodeplus" : do_rencodeplus, "rencode" : do_rencode, "bencode" : do_bencode, "yaml" : do_yaml, @@ -141,13 +168,15 @@ def get_packet_encoding_caps(): def get_enabled_encoders(order=ALL_ENCODERS): enabled = [x for x,b in { + "rencodeplus" : use_rencodeplus, "rencode" : use_rencode, "bencode" : use_bencode, "yaml" : use_yaml, }.items() if b] - log("get_enabled_encoders(%s) enabled=%s", order, enabled) + r = [x for x in order if x in enabled] + log.warn("get_enabled_encoders(%s)=%s enabled=%s", order, r, enabled) #order them: - return [x for x in order if x in enabled] + return r def get_encoder(e): @@ -164,6 +193,8 @@ def get_encoder_name(e): def get_packet_encoding_type(protocol_flags): + if protocol_flags & FLAGS_RENCODEPLUS: + return "rencodeplus" if protocol_flags & FLAGS_RENCODE: return "rencode" if protocol_flags & FLAGS_YAML: @@ -184,6 +215,12 @@ class InvalidPacketEncodingException(Exception): def decode(data, protocol_flags): if isinstance(data, memoryview): data = data.tobytes() + if protocol_flags & FLAGS_RENCODEPLUS: + if not has_rencodeplus: + raise InvalidPacketEncodingException("rencodeplus is not available") + if not use_rencodeplus: + raise InvalidPacketEncodingException("rencodeplus is disabled") + return list(rencodeplus_loads(data)) if protocol_flags & FLAGS_RENCODE: if not has_rencode: raise InvalidPacketEncodingException("rencode is not available")