Skip to content

Commit

Permalink
#614 fixes and improvements:
Browse files Browse the repository at this point in the history
* if we never got a packet back from the server, warn that compression or packet encoding may be wrong
* don't get compression has_xx / use_xx from protocol class
* move flags to header module
* move decompress and packet parsing to their module
* deal with races which can make "self._conn" None in get_info
* check the "use_XXX" flag when enableing an encoder! (not has_XX)
* if we fail to negotiate an encoder, fail with a helpful message

git-svn-id: https://xpra.org/svn/Xpra/trunk@6969 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jul 27, 2014
1 parent 33b831b commit b05c313
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 84 deletions.
7 changes: 7 additions & 0 deletions src/xpra/client/client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,13 @@ def _process_disconnect(self, packet):
self.warn_and_quit(e, "server requested disconnect: %s" % info)

def _process_connection_lost(self, packet):
p = self._protocol
if p and p.input_raw_packetcount==0:
props = p.get_info()
c = props.get("compression", "unknown")
e = props.get("encoder", "unknown")
log.warn("disconnected without receiving a single packet, not an xpra server?")
log.warn("(maybe it does not support '%s' compression or '%s' packet encoding)", c, e)
self.warn_and_quit(EXIT_CONNECTION_LOST, "Connection lost")

def _process_challenge(self, packet):
Expand Down
6 changes: 3 additions & 3 deletions src/xpra/client/window_backing_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from threading import Lock
from xpra.net.mmap_pipe import mmap_read
from xpra.net.protocol import has_lz4, LZ4_uncompress
from xpra.net import compression
from xpra.util import typedict
from xpra.codecs.codec_constants import get_colorspace_from_avutil_enum, get_PIL_decodings
from xpra.codecs.loader import get_codec
Expand Down Expand Up @@ -183,8 +183,8 @@ def process_delta(self, raw_data, width, height, rowstride, options):
if options.intget("zlib", 0)>0:
img_data = zlib.decompress(raw_data)
elif options.boolget("lz4", False):
assert has_lz4
img_data = LZ4_uncompress(raw_data)
assert compression.use_lz4
img_data = compression.LZ4_uncompress(raw_data)
if len(img_data)!=rowstride * height:
log.error("invalid img data %s: %s", type(img_data), str(img_data)[:256])
raise Exception("expected %s bytes for %sx%s with rowstride=%s but received %s (%s compressed)" %
Expand Down
38 changes: 32 additions & 6 deletions src/xpra/net/compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@

from xpra.log import Logger
log = Logger("network", "protocol")
debug = log.debug


ZLIB_FLAG = 0x00
LZ4_FLAG = 0x10
BZ2_FLAG = 0x20
from xpra.net.header import LZ4_FLAG, ZLIB_FLAG, BZ2_FLAG


try:
Expand Down Expand Up @@ -64,6 +59,15 @@ def nocompress(packet, level):
use_lz4 = has_lz4


def get_compression_caps():
return {
"lz4" : use_lz4,
"bz2" : use_bz2,
"zlib" : use_zlib,
"zlib.version" : zlib.__version__,
}


class Compressed(object):
def __init__(self, datatype, data):
self.datatype = datatype
Expand Down Expand Up @@ -94,3 +98,25 @@ def compressed_wrapper(datatype, data, level=5, lz4=False):
algo = "zlib"
cl, cdata = zcompress(data, level)
return LevelCompressed(datatype, cdata, cl, algo)


def get_compression_type(level):
if level & LZ4_FLAG:
return "lz4"
elif level & BZ2_FLAG:
return "bz2"
else:
return "zlib"

def decompress(data, level):
#log.info("decompress(%s bytes, %s) type=%s", len(data), get_compression_type(level))
if level & LZ4_FLAG:
assert has_lz4, "lz4 is not available"
assert use_lz4, "lz4 is not enabled"
return LZ4_uncompress(data)
elif level & BZ2_FLAG:
assert use_bz2, "bz2 is not enabled"
return bz2.decompress(data)
else:
assert use_zlib, "zlib is not enabled"
return zlib.decompress(data)
10 changes: 10 additions & 0 deletions src/xpra/net/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
import struct


ZLIB_FLAG = 0x0 #assume zlib if no other compression flag is set
FLAGS_RENCODE = 0x1
FLAGS_CIPHER = 0x2
FLAGS_YAML = 0x4
#0x8 is free
LZ4_FLAG = 0x10
BZ2_FLAG = 0x20
FLAGS_NOHEADER = 0x40
#0x80 is free

if sys.version_info[:2]>=(2,5):
def unpack_header(buf):
return struct.unpack_from('!cBBBL', buf)
Expand Down
42 changes: 41 additions & 1 deletion src/xpra/net/packet_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from xpra.log import Logger
log = Logger("network", "protocol")
debug = log.debug
from xpra.net.header import FLAGS_RENCODE, FLAGS_YAML #, FLAGS_BENCODE


rencode_dumps, rencode_loads, rencode_version = None, None, None
Expand Down Expand Up @@ -54,3 +54,43 @@
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("packet encoding: has_yaml=%s, use_yaml=%s, version=%s", has_yaml, use_yaml, yaml_version)


def get_packet_encoding_caps():
caps = {
"rencode" : use_rencode,
"bencode" : use_bencode,
"yaml" : use_yaml,
}
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

def get_packet_encoding_type(protocol_flags):
if protocol_flags & FLAGS_RENCODE:
return "rencode"
elif protocol_flags & FLAGS_YAML:
return "yaml"
else:
return "bencode"

def decode(data, protocol_flags):
if protocol_flags & FLAGS_RENCODE:
assert has_rencode, "we don't support rencode mode but the other end sent us a rencoded packet! not an xpra client?"
return list(rencode_loads(data))
elif protocol_flags & FLAGS_YAML:
assert has_yaml, "we don't support yaml mode but the other end sent us a yaml packet! not an xpra client?"
return list(yaml_decode(data))
else:
#if sys.version>='3':
# data = data.decode("latin1")
packet, l = bdecode(data)
assert l==len(data)
return packet
Loading

0 comments on commit b05c313

Please sign in to comment.