Skip to content

Commit

Permalink
* add cython bencoder and use it by default if present
Browse files Browse the repository at this point in the history
* make bencoder optional (use rencode as fallback)

git-svn-id: https://xpra.org/svn/Xpra/trunk@5076 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jan 1, 2014
1 parent d114e4f commit bc2bf21
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 51 deletions.
19 changes: 18 additions & 1 deletion src/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
opengl_ENABLED = client_ENABLED
html5_ENABLED = True

bencode_ENABLED = True
cython_bencode_ENABLED = True
rencode_ENABLED = True
cymaths_ENABLED = True
cyxor_ENABLED = True
Expand Down Expand Up @@ -81,7 +83,9 @@
"csc_swscale", "swscale_static",
"csc_nvcuda", "csc_opencl", "csc_cython",
"vpx", "vpx_static",
"webp", "rencode", "clipboard",
"webp",
"rencode", "bencode", "cython_bencode",
"clipboard",
"server", "client", "x11",
"gtk2", "gtk3", "qt4", "html5",
"sound", "cyxor", "cymaths", "opengl", "argb",
Expand Down Expand Up @@ -1128,6 +1132,19 @@ def pkgconfig(*packages_options, **ekw):
**rencode_pkgconfig))


toggle_packages(bencode_ENABLED, "xpra.net.bencode")
if cython_bencode_ENABLED:
bencode_pkgconfig = pkgconfig()
if not debug_ENABLED:
if WIN32:
add_to_keywords(bencode_pkgconfig, 'extra_compile_args', "/Ox")
else:
add_to_keywords(bencode_pkgconfig, 'extra_compile_args', "-O3")
cython_add(Extension("xpra.net.bencode.cython_bencode",
["xpra/net/bencode/cython_bencode.pyx"],
**bencode_pkgconfig))


if ext_modules:
setup_options["ext_modules"] = ext_modules
if cmdclass:
Expand Down
138 changes: 97 additions & 41 deletions src/tests/xpra/net/test_bencode.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,61 @@
# 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.bencode import bencode, bdecode
import time
from xpra.util import nonl
encode, decode = None, None

def use_cython():
global encode, decode
from xpra.net.bencode.cython_bencode import bencode, bdecode
encode = bencode
decode = bdecode

def use_python():
global encode, decode
from xpra.net.bencode.bencode import bencode, bdecode
encode = bencode
decode = bdecode

def plog(x):
print(x)
def noop(x):
pass
log = plog

def use_print():
global log
log = plog
def use_noop():
global log
log = noop



def i(s):
v = nonl(str(s))
if len(v)<48:
return v
return v[:46]+".."


def test_decoding():

def t(s, value, remainder):
print(s)
#log(" "+i(s))
# Test "one-shot":
rv, rr = bdecode(s)
rv, rr = decode(s)
assert rv == value, "expected value %s but got %s" % (rv, value)
rrstr = s[rr:]
assert rrstr == remainder, "expected remainder value %s but got %s" % (remainder, rrstr)
# With gibberish added:
g_str = s + "asdf"
rv, rr = bdecode(g_str)
rv, rr = decode(g_str)
assert rv == value, "expected value %s but got %s" % (rv, value)
rrstr = g_str[rr:]
assert rrstr.endswith("asdf")

t("l16:configure-windowi2ei555ei340ei649ei381ed9:maximizedi0e6:screeni0e9:maximizedi0eee", [], "")
#t("l16:configure-windowi2ei555ei340ei649ei381ed9:maximizedi0e6:screeni0e9:maximizedi0eee", [], "")

t("i12345e", 12345, "")
t("i-12345e", -12345, "")
Expand All @@ -41,15 +77,15 @@ def t(s, value, remainder):
# Keys do not have to be strings:
t("di0ei0ee", {0 : 0}, "")

print("------")
def te(s, exc):
print(s)
#log(" "+s)
v = None
try:
bdecode(s)
v = decode(s)
except exc:
pass
else:
assert False, "didn't raise exception"
assert False, "didn't raise exception, returned: %s for %s" % (v, s)

te("iie", ValueError)
te("i0x0e", ValueError)
Expand All @@ -60,45 +96,36 @@ def te(s, exc):
te("-1:aa", ValueError)
te("02:aa", ValueError)

# Keys must be in ascending order:
te("d1:bi0e1:ai0e1:ci0ee", ValueError)
te("d1:ai0e1:ci0e1:bi0ee", ValueError)

te("l5:hellod20:__prerelease_version8:0.0.7.2612:desktop_sizeli480ei800ee4:jpegi40e18:challenge_response40:ba59e4110119264f4a6eaf3adc075ea2c5408550ee", ValueError)
#no idea why this does not fail if the one above does!:
#te("l5:hellod20:__prerelease_version8:0.0.7.2618:challenge_response40:ba59e4110119264f4a6eaf3adc075ea2c540855012:desktop_sizeli480ei800ee4:jpegi40eee", ValueError)


def test_encoding():

def t(v, encstr=None):
be = bencode(v)
print("bencode(%s)=%s" % (v, be))
be = encode(v)
log("bencode(%s)=%s" % (i(v), i(be)))
if encstr:
assert be==encstr
restored = bdecode(be)
print("decode(%s)=%s" % (be, restored))
restored = decode(be)
log("decode(%s)=%s" % (i(be), i(restored)))
rlist = restored[0]
if len(rlist)!=len(v):
print("MISMATCH!")
print("v=%s" % v)
print("l=%s" % rlist)
log("MISMATCH!")
log("v=%s" % v)
log("l=%s" % rlist)
assert len(rlist)==2
assert rlist[0]==v[0]
for ok,ov in v[1].items():
d = rlist[1]
if ok not in d:
print("restored dict is missing %s" % ok)
log("restored dict is missing %s" % ok)
return rlist
rv = d.get(ok)
if rv!=ov:
print("value for %s does not match: %s vs %s" % (ok, ov, rv))
log("value for %s does not match: %s vs %s" % (ok, ov, rv))
return rlist
return rlist

def test_hello():
print()
print("test_hello()")
log("test_hello()")
d = {}
d["__prerelease_version"] = "0.0.7.26"
#caps.put("deflate", 6);
Expand All @@ -109,10 +136,10 @@ def test_hello():
d["challenge_response"] = challenge
hello = ["hello", d]
t(hello, "l5:hellod20:__prerelease_version8:0.0.7.2618:challenge_response40:ba59e4110119264f4a6eaf3adc075ea2c540855012:desktop_sizeli480ei800ee4:jpegi4eee")
log("")

def test_large_hello():
print()
print("test_large_hello()")
log("test_large_hello()")
d = {'start_time': 1325786122,
'resize_screen': False, 'bell': True, 'desktop_size': [800, 600], 'modifiers_nuisance': True,
'actual_desktop_size': [3840, 2560], 'encodings': ['rgb24', 'jpeg', 'png'],
Expand All @@ -126,35 +153,64 @@ def test_large_hello():

d['some_new_feature_we_may_add'] = {"with_a_nested_dict" : {"containing_another_dict" : ["with", "nested", "arrays", ["in", ["it"]]]}}
t(hello, "l5:hellod20:__prerelease_version8:0.0.7.3319:actual_desktop_sizeli3840ei2560ee4:belli1e9:clipboardi1e7:cursorsi1e15:damage_sequencei1e12:desktop_sizeli800ei600ee8:encoding5:rgb249:encodingsl5:rgb244:jpeg3:pnge23:focus_modifiers_featurei1e18:modifiers_nuisancei1e13:notificationsi1e11:packet_sizei1e4:pingi1e8:platform6:linux216:png_window_iconsi1e20:raw_keycodes_featurei1e13:resize_screeni0e27:some_new_feature_we_may_addd18:with_a_nested_dictd23:containing_another_dictl4:with6:nested6:arraysl2:inl2:iteeeee10:start_timei1325786122eee")

log("")

test_hello()
test_large_hello()


def test_random():
log("test_random()")
import binascii
u = "6c343a6472617769316569333731656931356569366569313365353a726762333231343a7801fbff7f1490130200099e36d8693265693234656431303a7267625f666f726d6174343a52474258343a7a6c69626931656565"
s = binascii.unhexlify(u)
bdecode(s)
decode(s)
log("")

def test_large_dict():
log("test_large_dict()")
try:
from xpra.x11.gtk_x11 import gdk_display_source #@UnusedImport
from xpra.x11.bindings.keyboard_bindings import X11KeyboardBindings #@UnresolvedImport
keyboard_bindings = X11KeyboardBindings()
mappings = keyboard_bindings.get_keycode_mappings()
b = bencode(mappings)
print("bencode(%s)=%s" % (mappings, b))
d = bdecode(b)
print("bdecode(%s)=%s" % (b, d))
b = encode(mappings)
log("bencode(%s)=%s" % (i(mappings), i(b)))
d = decode(b)
log("bdecode(%s)=%s" % (i(b), i(d)))
except ImportError, e:
print("test_large_dict() skipped because of: %s" % e)
log("test_large_dict() skipped because of: %s" % e)
log("")

def test_compare_cython():
log("test_compare_cython()")
#suspend logging:
use_noop()
results = {}
for n,x in {"python" : use_python, "cython" : use_cython}.items():
x()
start = time.time()
for i in range(100):
test_large_dict()
test_random()
test_decoding()
test_encoding()
end = time.time()
results[n] = int(1000.0*(end-start))
use_print()
log("results: %s (in milliseconds)" % results)


def main():
test_random()
test_decoding()
test_encoding()
test_large_dict()
for x in (use_python, use_cython):
log("main: testing with %s" % x)
x()
test_random()
test_decoding()
test_encoding()
test_large_dict()

test_compare_cython()


if __name__ == "__main__":
Expand Down
1 change: 0 additions & 1 deletion src/xpra/client/client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ def get_scheduler(self):
def setup_connection(self, conn):
log.debug("setup_connection(%s)", conn)
self._protocol = Protocol(self.get_scheduler(), conn, self.process_packet, self.next_packet)
self._protocol.enable_bencode()
self._protocol.large_packets.append("keymap-changed")
self._protocol.large_packets.append("server-settings")
self._protocol.set_compression_level(self.compression_level)
Expand Down
6 changes: 6 additions & 0 deletions src/xpra/net/bencode/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
try:
from xpra.net.bencode.cython_bencode import bencode, bdecode, __version__
except ImportError:
from xpra.net.bencode.bencode import bencode, bdecode, __version__

__all__ = ['bencode', 'bdecode', "__version__"]
2 changes: 2 additions & 0 deletions src/xpra/net/bencode.py → src/xpra/net/bencode/bencode.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

# Original version written by Petru Paler

__version__ = ("Python", 0, 11)

import sys
if sys.version > '3':
long = int #@ReservedAssignment
Expand Down
Loading

0 comments on commit bc2bf21

Please sign in to comment.