Skip to content

Commit

Permalink
add support for yaml as packet encoder
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@6934 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jul 23, 2014
1 parent f67037d commit 8d8ed0c
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 8 deletions.
24 changes: 24 additions & 0 deletions src/tests/xpra/net/test_yaml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python
# coding=utf8
# This file is part of Xpra.
# Copyright (C) 2014 Antoine Martin <[email protected]>
# 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.net.protocol import yaml_encode,yaml_decode

def test():
d = [12, {'pycrypto.version': '2.6.1', 'window.resize-counter': True, 'build.version': '0.14.0'}]
v = yaml_encode(d)
d2 = yaml_decode(v)
print("yaml_encode(%s)=%s" % (d, v))
print("yaml_decode(%s)=%s" % (v, d2))
assert d2


def main():
test()


if __name__ == "__main__":
main()
4 changes: 3 additions & 1 deletion src/xpra/client/client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from xpra.log import Logger
log = Logger("client")

from xpra.net.protocol import Protocol, use_lz4, use_rencode, get_network_caps
from xpra.net.protocol import Protocol, use_lz4, use_rencode, use_yaml, get_network_caps
from xpra.scripts.config import ENCRYPTION_CIPHERS
from xpra.version_util import version_compat_check, get_version_info, get_platform_info, local_version
from xpra.platform.features import GOT_PASSWORD_PROMPT_SUGGESTION
Expand Down Expand Up @@ -497,6 +497,8 @@ def parse_network_capabilities(self):
c = self.server_capabilities
if use_rencode and c.boolget("rencode"):
self._protocol.enable_rencode()
elif use_yaml and c.boolget("yaml"):
self._protocol.enable_yaml()
if use_lz4 and c.boolget("lz4") and self.compression_level==1:
self._protocol.enable_lz4()
if self.encryption:
Expand Down
4 changes: 3 additions & 1 deletion src/xpra/client/gtk_base/session_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,8 @@ def get_encoder_list(caps):
l.append("bencode")
if caps.get("rencode", False):
l.append("rencode")
if caps.get("yaml", False):
l.append("yaml")
return l
self.client_packet_encoders_label.set_text(", ".join(get_encoder_list(get_network_caps())))
self.server_packet_encoders_label.set_text(", ".join(get_encoder_list(self.client.server_capabilities)))
Expand Down Expand Up @@ -695,7 +697,7 @@ def set_sound_info(label, details, supported, prop):
if level==0:
compression_str = "None"
else:
compression_str = " + ".join([x for x in ("zlib", "lz4", "bencode", "rencode") if protocol_state.get(x, False)==True])
compression_str = " + ".join([x for x in ("zlib", "lz4", "bencode", "rencode", "yaml") if protocol_state.get(x, False)==True])
compression_str += ", level %s" % level
self.compression_label.set_text(compression_str)

Expand Down
13 changes: 12 additions & 1 deletion src/xpra/client/ui_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,13 +912,21 @@ def make_hello(self):
"encodings.core" : self.get_core_encodings(),
})
control_commands = ["show_session_info", "enable_bencode", "enable_zlib"]
from xpra.net.protocol import use_bencode, use_rencode
from xpra.net.protocol import use_bencode, use_rencode, use_yaml
for k,b in {"lz4" : use_lz4,
"bencode" : use_bencode,
"rencode" : use_rencode,
"yaml" : use_yaml}.items():
if b:
control_commands.append("enable_"+k)
if use_lz4:
control_commands.append("enable_lz4")
if use_bencode:
control_commands.append("enable_bencode")
if use_rencode:
control_commands.append("enable_rencode")
if use_yaml:
control_commands.append("enable_yaml")
capabilities["control_commands"] = control_commands
for k,v in codec_versions.items():
capabilities["encoding.%s.version" % k] = v
Expand Down Expand Up @@ -1361,6 +1369,9 @@ def _process_control(self, packet):
elif command=="enable_rencode":
log.info("switching to rencode on server request")
self._protocol.enable_rencode()
elif command=="enable_yaml":
log.info("switching to yaml on server request")
self._protocol.enable_yaml()
elif command=="name":
assert len(args)>=3
self.session_name = args[2]
Expand Down
43 changes: 40 additions & 3 deletions src/xpra/net/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ def lz4_compress(packet, level):
use_bencode = has_bencode and os.environ.get("XPRA_USE_BENCODER", "1")=="1"
log("protocol: has_bencode=%s, use_bencode=%s, version=%s", has_bencode, use_bencode, bencode_version)

yaml_encode, yaml_decode, yaml_version = None, None, None
try:
#json messes with strings and unicode (makes it unusable for us)
import yaml
yaml_encode = yaml.dump
yaml_decode = yaml.load
yaml_version = yaml.__version__
except ImportError:
log("yaml not found")
has_yaml = yaml_encode is not None and yaml_decode is not None
use_yaml = has_yaml and os.environ.get("XPRA_USE_YAML", "1")=="1"
log("protocol: has_yaml=%s, use_yaml=%s, version=%s", has_yaml, use_yaml, yaml_version)


#stupid python version breakage:
if sys.version > '3':
long = int #@ReservedAssignment
Expand Down Expand Up @@ -148,6 +162,7 @@ def get_network_caps(legacy=True):
"digest" : ("hmac", "xor"),
"rencode" : use_rencode,
"bencode" : use_bencode,
"yaml" : use_yaml,
"lz4" : use_lz4,
"mmap" : mmap,
}
Expand All @@ -170,9 +185,14 @@ def get_network_caps(legacy=True):
pass

if has_rencode:
assert rencode_version is not None
caps["rencode.version"] = rencode_version
if has_bencode:
assert bencode_version is not None
caps["bencode.version"] = bencode_version
if has_yaml:
assert yaml_version is not None
caps["yaml.version"] = yaml_version
return caps


Expand Down Expand Up @@ -229,6 +249,7 @@ class Protocol(object):

FLAGS_RENCODE = 0x1
FLAGS_CIPHER = 0x2
FLAGS_JSON = 0x4
FLAGS_NOHEADER = 0x40

def __init__(self, scheduler, conn, process_packet_cb, get_packet_cb=None):
Expand Down Expand Up @@ -257,7 +278,7 @@ def __init__(self, scheduler, conn, process_packet_cb, get_packet_cb=None):
self.output_packetcount = 0
self.output_raw_packetcount = 0
#initial value which may get increased by client/server after handshake:
self.max_packet_size = 32*1024
self.max_packet_size = 256*1024
self.abs_max_packet_size = 32*1024*1024
self.large_packets = ["hello"]
self.send_aliases = {}
Expand Down Expand Up @@ -293,6 +314,7 @@ def save_state(self):
state["lz4"] = lz4_compress and self._compress==lz4_compress
state["bencode"] = self._encoder == self.bencode
state["rencode"] = self._encoder == self.rencode
state["yaml"] = self._encoder == self.yaml
#state["connection"] = self._conn
return state

Expand All @@ -305,6 +327,8 @@ def restore_state(self, state):
self.enable_lz4()
if state.get("rencode", False):
self.enable_rencode()
elif state.get("yaml", False):
self.enable_yaml()

def wait_for_io_threads_exit(self, timeout=None):
for t in (self._read_thread, self._write_thread):
Expand Down Expand Up @@ -524,6 +548,12 @@ def enable_rencode(self):
log("enable_rencode()")
self._encoder = self.rencode

def enable_yaml(self):
assert has_yaml, "yaml cannot be enabled: the module failed to load!"
log("enable_yaml()")
self._encoder = self.yaml


def enable_zlib(self):
log("enable_zlib()")
self._compress = zcompress
Expand All @@ -543,6 +573,10 @@ def bencode(self, data):
def rencode(self, data):
return rencode_dumps(data), Protocol.FLAGS_RENCODE

def yaml(self, data):
return yaml_encode(data), Protocol.FLAGS_JSON


def encode(self, packet_in):
"""
Given a packet (tuple or list of items), converts it for the wire.
Expand Down Expand Up @@ -605,11 +639,11 @@ def encode(self, packet_in):
packet[0] = packet_type
self.verify_packet(packet)
raise e
if len(main_packet)>LARGE_PACKET_SIZE and packet_in[0] not in self.large_packets:
if False and len(main_packet)>LARGE_PACKET_SIZE and packet_in[0] not in self.large_packets:
log.warn("found large packet (%s bytes): %s, argument types:%s, sizes: %s, packet head=%s",
len(main_packet), packet_in[0], [type(x) for x in packet[1:]], [len(str(x)) for x in packet[1:]], repr_ellipsized(packet))
#compress, but don't bother for small packets:
if level>0 and len(main_packet)>min_comp_size:
if False and level>0 and len(main_packet)>min_comp_size:
cl, cdata = self._compress(main_packet, level)
packets.append((0, cl, cdata))
else:
Expand Down Expand Up @@ -856,6 +890,9 @@ def debug_str(s):
if protocol_flags & Protocol.FLAGS_RENCODE:
assert has_rencode, "we don't support rencode mode but the other end sent us a rencoded packet! not an xpra client?"
packet = list(rencode_loads(data))
elif protocol_flags & Protocol.FLAGS_JSON:
assert has_yaml, "we don't support yaml mode but the other end sent us a yaml packet! not an xpra client?"
packet = list(yaml_decode(data))
else:
#if sys.version>='3':
# data = data.decode("latin1")
Expand Down
2 changes: 2 additions & 0 deletions src/xpra/server/proxy_instance_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ def filter_client_caps(self, caps):
def filter_server_caps(self, caps):
if caps.get("rencode", False):
self.server_protocol.enable_rencode()
elif caps.get("yaml", False):
self.server_protocol.enable_yaml()
return self.filter_caps(caps, ("aliases", ))

def filter_caps(self, caps, prefixes):
Expand Down
10 changes: 9 additions & 1 deletion src/xpra/server/server_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,10 @@ def debug_usage():
if len(args)!=1:
return argn_err(1)
encoder = args[0].lower()
opts = ("bencode", "rencode")
from xpra.net.protocol import use_bencode, use_rencode, use_yaml
opts = [x for x,b in {"bencode" : use_bencode,
"rencode" : use_rencode,
"yaml" : use_yaml}.items() if b]
if encoder=="bencode":
for cproto in protos:
cproto.enable_bencode()
Expand All @@ -821,6 +824,11 @@ def debug_usage():
cproto.enable_rencode()
forward_all_clients(["enable_rencode"])
return success()
elif encoder=="yaml":
for cproto in protos:
cproto.enable_yaml()
forward_all_clients(["enable_yaml"])
return success()
return arg_err("must be one of: %s" % (", ".join(opts)))
elif command=="sound-output":
if len(args)<1:
Expand Down
4 changes: 3 additions & 1 deletion src/xpra/server/server_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from xpra.platform import set_application_name
from xpra.os_util import load_binary_file, get_machine_id, get_user_uuid, SIGNAMES
from xpra.version_util import version_compat_check, get_version_info, get_platform_info, get_host_info, local_version, mk
from xpra.net.protocol import Protocol, use_lz4, use_rencode, new_cipher_caps, get_network_caps, repr_ellipsized
from xpra.net.protocol import Protocol, use_lz4, use_rencode, use_yaml, new_cipher_caps, get_network_caps, repr_ellipsized
from xpra.server.background_worker import stop_worker
from xpra.daemon_thread import make_daemon_thread
from xpra.server.proxy import XpraProxy
Expand Down Expand Up @@ -408,6 +408,8 @@ def _process_hello(self, proto, packet):
proto.set_compression_level(c.intget("compression_level", self.compression_level))
if use_rencode and c.boolget("rencode"):
proto.enable_rencode()
elif use_yaml and c.boolget("yaml"):
proto.enable_yaml()
else:
proto.enable_bencode()

Expand Down

0 comments on commit 8d8ed0c

Please sign in to comment.