def get_env(self): env = os.environ.copy() env["XPRA_SKIP_UI"] = "1" env["XPRA_LOG_PREFIX"] = "%s " % self.description #let's make things more complicated than they should be: #on win32, the environment can end up containing unicode, and subprocess chokes on it for k,v in env.items(): try: env[k] = bytestostr(v.encode("utf8")) except: env[k] = bytestostr(v) return env
def check(self, str_value): b = strtobytes(str_value) assert b s = bytestostr(b) assert s assert s==str_value if not _memoryview: return mv = _memoryview(b) mvb = memoryview_to_bytes(mv) mvs = bytestostr(mvb) assert mvs==str_value
def exec_env(blacklist=["LS_COLORS", ]): env = os.environ.copy() env["XPRA_SKIP_UI"] = "1" env["XPRA_FORCE_COLOR_LOG"] = "1" #let's make things more complicated than they should be: #on win32, the environment can end up containing unicode, and subprocess chokes on it for k,v in env.items(): if k in blacklist: continue try: env[k] = bytestostr(v.encode("utf8")) except: env[k] = bytestostr(v) return env
def _process_hello(self, packet): log.debug("process_hello: %s", packet) props = packet[1] if props: def sorted_nicely(l): """ Sort the given iterable in the way that humans expect.""" def convert(text): if text.isdigit(): return int(text) else: return text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', bytestostr(key)) ] return sorted(l, key = alphanum_key) for k in sorted_nicely(props.keys()): v = props.get(k) if sys.version_info[0]>=3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only def fixvalue(w): if type(w)==bytes: return bytestostr(w) elif type(w) in (tuple,list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) log.info("%s=%s", bytestostr(k), nonl(v)) self.quit(0)
def _process_gibberish(self, packet): (_, message, data) = packet p = self._protocol show_as_text = p and p.input_packetcount==0 and all(c in string.printable for c in bytestostr(data)) if show_as_text: #looks like the first packet back is just text, print it: data = bytestostr(data) if data.find("Traceback "): for x in data.split("\n"): log.warn(x.strip("\r")) else: log.warn("Failed to connect, received: %s", repr_ellipsized(data.strip("\n").strip("\r"))) else: log.warn("Received uninterpretable nonsense: %s", message) log.warn(" packet no %i data: %s", p.input_packetcount, repr_ellipsized(data)) if str(data).find("assword")>0: self.warn_and_quit(EXIT_SSH_FAILURE, "Your ssh program appears to be asking for a password." + GOT_PASSWORD_PROMPT_SUGGESTION) elif str(data).find("login")>=0: self.warn_and_quit(EXIT_SSH_FAILURE, "Your ssh program appears to be asking for a username.\n" "Perhaps try using something like 'ssh:USER@host:display'?") else: self.quit(EXIT_PACKET_FAILURE)
def draw_region(self, x, y, width, height, coding, img_data, rowstride, options, callbacks): """ dispatches the paint to one of the paint_XXXX methods """ if DRAW_DEBUG: log.info("draw_region(%s, %s, %s, %s, %s, %s bytes, %s, %s, %s)", x, y, width, height, coding, len(img_data), rowstride, options, callbacks) coding = bytestostr(coding) if coding == "mmap": self.idle_add(self.paint_mmap, img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb24": if rowstride==0: rowstride = width * 3 self.paint_rgb24(img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb32": if rowstride==0: rowstride = width * 4 self.paint_rgb32(img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "x264": self.paint_with_video_decoder(dec_avcodec, "x264", img_data, x, y, width, height, options, callbacks) elif coding == "vpx": self.paint_with_video_decoder(dec_vpx, "vpx", img_data, x, y, width, height, options, callbacks) elif coding == "webp": self.paint_webp(img_data, x, y, width, height, options, callbacks) elif coding[:3]=="png" or coding=="jpeg": self.paint_image(coding, img_data, x, y, width, height, options, callbacks) else: raise Exception("invalid encoding: %s" % coding)
def draw_region(self, x, y, width, height, coding, img_data, rowstride, options, callbacks): """ dispatches the paint to one of the paint_XXXX methods """ log("draw_region(%s, %s, %s, %s, %s, %s bytes, %s, %s, %s)", x, y, width, height, coding, len(img_data), rowstride, options, callbacks) coding = bytestostr(coding) options["encoding"] = coding #used for choosing the color of the paint box if coding == "mmap": self.idle_add(self.paint_mmap, img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb24" or coding == "rgb32": #avoid confusion over how many bytes-per-pixel we may have: rgb_format = options.get("rgb_format") if rgb_format: Bpp = len(rgb_format) elif coding=="rgb24": Bpp = 3 else: Bpp = 4 if rowstride==0: rowstride = width * Bpp if Bpp==3: self.paint_rgb24(img_data, x, y, width, height, rowstride, options, callbacks) else: self.paint_rgb32(img_data, x, y, width, height, rowstride, options, callbacks) elif coding in VIDEO_DECODERS: self.paint_with_video_decoder(VIDEO_DECODERS.get(coding), coding, img_data, x, y, width, height, options, callbacks) elif coding == "webp": self.paint_webp(img_data, x, y, width, height, options, callbacks) elif coding in self._PIL_encodings: self.paint_image(coding, img_data, x, y, width, height, options, callbacks) else: self.do_draw_region(x, y, width, height, coding, img_data, rowstride, options, callbacks)
def listget(self, k, default_value=[], item_type=None, max_items=None): v = self.capsget(k, default_value) if v is None: return default_value if type(v) not in (list, tuple): typedict.log.warn("expected a list or tuple value for %s but got %s", k, type(v)) return default_value aslist = list(v) if item_type: for i in range(len(aslist)): x = aslist[i] if sys.version > '3' and type(x)==bytes and item_type==str: x = bytestostr(x) aslist[i] = x elif type(x)==unicode and item_type==str: x = str(x) aslist[i] = x if type(x)!=item_type: typedict.log.warn("invalid item type for %s %s: expected %s but got %s", type(v), k, item_type, type(x)) return default_value if max_items is not None: if len(v)>max_items: typedict.log.warn("too many items in %s %s: maximum %s allowed, but got %s", type(v), k, max_items, len(v)) return default_value return aslist
def capsget(self, key, default=None): v = self.get(key) #py3k and bytes as keys... if v is None and type(key)==str: v = self.get(strtobytes(key), default) if sys.version >= '3' and type(v)==bytes: v = bytestostr(v) return v
def sorted_nicely(l): """ Sort the given iterable in the way that humans expect.""" def convert(text): if text.isdigit(): return int(text) else: return text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', bytestostr(key)) ] return sorted(l, key = alphanum_key)
def _process_disconnect(self, packet): #ie: ("disconnect", "version error", "incompatible version") reason = bytestostr(packet[1]) info = packet[2:] s = nonl(reason) if len(info): s += " (%s)" % (", ".join([nonl(bytestostr(x)) for x in info])) if self.server_capabilities is None or len(self.server_capabilities)==0: #server never sent hello to us - so disconnect is an error #(but we don't know which one - the info message may help) log.warn("server failure: disconnected before the session could be established") e = EXIT_FAILURE elif disconnect_is_an_error(reason): log.warn("server failure: %s", reason) e = EXIT_FAILURE else: e = EXIT_OK self.warn_and_quit(e, "server requested disconnect: %s" % s)
def test_env(self): for var_name in ("XPRA_PASSWORD", "SOME_OTHER_VAR_NAME"): password = strtobytes(uuid.uuid4().hex) os.environ[var_name] = bytestostr(password) try: kwargs = {} if var_name!="XPRA_PASSWORD": kwargs["name"] = var_name self._test_hmac_auth(env_auth, password, name=var_name) finally: del os.environ[var_name]
def do_command(self): cr = self.server_capabilities.listget("command_response") if cr is None: self.warn_and_quit(EXIT_UNSUPPORTED, "server does not support control command") return code, text = cr text = bytestostr(text) if code!=0: log.warn("server returned error code %s", code) self.warn_and_quit(EXIT_REMOTE_ERROR, " %s" % text) return self.warn_and_quit(EXIT_OK, text)
def _process_gibberish(self, packet): (_, message, data) = packet p = self._protocol show_as_text = p and p.input_packetcount==0 and all(c in string.printable for c in bytestostr(data)) if show_as_text: #looks like the first packet back is just text, print it: data = bytestostr(data) if data.find("Traceback "): for x in data.split("\n"): netlog.warn(x.strip("\r")) else: netlog.warn("Failed to connect, received: %s", repr_ellipsized(data.strip("\n").strip("\r"))) else: netlog.warn("Received uninterpretable nonsense: %s", message) netlog.warn(" packet no %i data: %s", p.input_packetcount, repr_ellipsized(data)) self.quit(EXIT_PACKET_FAILURE)
def apply_geometry_hints(self, hints): """ we convert the hints as a dict into a gdk.Geometry + gdk.WindowHints """ wh = Gdk.WindowHints name_to_hint = {"maximum-size" : wh.MAX_SIZE, "max_width" : wh.MAX_SIZE, "max_height" : wh.MAX_SIZE, "minimum-size" : wh.MIN_SIZE, "min_width" : wh.MIN_SIZE, "min_height" : wh.MIN_SIZE, "base-size" : wh.BASE_SIZE, "base_width" : wh.BASE_SIZE, "base_height" : wh.BASE_SIZE, "increment" : wh.RESIZE_INC, "width_inc" : wh.RESIZE_INC, "height_inc" : wh.RESIZE_INC, "min_aspect_ratio" : wh.ASPECT, "max_aspect_ratio" : wh.ASPECT, } #these fields can be copied directly to the gdk.Geometry as ints: INT_FIELDS= ["min_width", "min_height", "max_width", "max_height", "base_width", "base_height", "width_inc", "height_inc"] ASPECT_FIELDS = { "min_aspect_ratio" : "min_aspect", "max_aspect_ratio" : "max_aspect", } geom = Gdk.Geometry() mask = 0 for k,v in hints.items(): k = bytestostr(k) if k in INT_FIELDS: if k.find("width")>=0: v = self._client.sx(v) elif k.find("height")>=0: v = self._client.sy(v) elif k.find("size")>=0: v = self._client.sp(v) setattr(geom, k, int(v)) mask |= int(name_to_hint.get(k, 0)) elif k in ASPECT_FIELDS: field = ASPECT_FIELDS.get(k) setattr(geom, field, float(v)) mask |= int(name_to_hint.get(k, 0)) gdk_hints = Gdk.WindowHints(mask) metalog("apply_geometry_hints(%s) geometry=%s, hints=%s", hints, geom, gdk_hints) self.set_geometry_hints(None, geom, gdk_hints)
def pver(v): if type(v) in (tuple, list): s = "" for i in range(len(v)): if i>0: #dot seperated numbers if type(v[i-1])==int: s += "." else: s += ", " s += str(v[i]) return s if type(v)==bytes: from xpra.os_util import bytestostr v = bytestostr(v) if type(v)==str and v.startswith("v"): return v[1:] return str(v)
def process_packet(self, proto, packet): try: handler = None packet_type = packet[0] if packet_type!=int: packet_type = bytestostr(packet_type) handler = self._packet_handlers.get(packet_type) if handler: handler(packet) return handler = self._ui_packet_handlers.get(packet_type) if not handler: log.error("unknown packet type: %s", packet_type) return self.idle_add(handler, packet) except KeyboardInterrupt: raise except: log.error("Unhandled error while processing a '%s' packet from peer using %s", packet_type, handler, exc_info=True)
def listget(self, k, default_value=[], item_type=None, max_items=None): v = self.capsget(k, default_value) if v is None: return default_value assert type(v) in (list, tuple), "expected a list or tuple value for %s but got %s" % (k, type(v)) aslist = list(v) if item_type: for i in range(len(aslist)): x = aslist[i] if sys.version > '3' and type(x)==bytes and item_type==str: x = bytestostr(x) aslist[i] = x elif type(x)==unicode and item_type==str: x = str(x) aslist[i] = x assert type(x)==item_type, "invalid item type for %s %s: expected %s but got %s" % (type(v), k, item_type, type(x)) if max_items is not None: assert len(v)<=max_items, "too many items in %s %s: maximum %s allowed, but got %s" % (type(v), k, max_items, len(v)) return aslist
def do_command(self): if self.server_capabilities: if FLATTEN_INFO<2: #compatibility mode: for k in sorted_nicely(self.server_capabilities.keys()): v = self.server_capabilities.get(k) if sys.version_info[0]>=3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only def fixvalue(w): if type(w)==bytes: return bytestostr(w) elif type(w) in (tuple,list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) log.info("%s=%s", bytestostr(k), nonl(v)) else: print_nested_dict(self.server_capabilities) self.quit(EXIT_OK)
def process_challenge_gss(self, packet): digest = packet[3] if not digest.startswith(b"gss:"): #not a gss challenge authlog("%s is not a gss challenge", digest) return False try: import gssapi if OSX and False: from gssapi.raw import (cython_converters, cython_types, oids) assert cython_converters and cython_types and oids except ImportError as e: authlog("import gssapi", exc_info=True) if first_time("no-kerberos"): authlog.warn("Warning: gss authentication not supported:") authlog.warn(" %s", e) return False service = bytestostr(digest.split(b":", 1)[1]) if service not in GSS_SERVICES and "*" not in GSS_SERVICES: authlog.warn("Warning: invalid GSS request for service '%s'", service) authlog.warn(" services supported: %s", csv(GSS_SERVICES)) return False authlog("gss service=%s", service) service_name = gssapi.Name(service) try: ctx = gssapi.SecurityContext(name=service_name, usage="initiate") token = ctx.step() except Exception as e: authlog("gssapi failure", exc_info=True) authlog.error("Error: gssapi client authentication failure:") try: #split on colon for x in str(e).split(":", 2): authlog.error(" %s", x.lstrip(" ")) except: authlog.error(" %s", e) return False authlog("gss token=%s", repr(token)) self.send_challenge_reply(packet, token) return True
def get_antialias_info(): info = {} try: from xpra.x11.xsettings_prop import XSettingsTypeInteger, XSettingsTypeString d = _get_xsettings_dict() for prop_name, name in { "Xft/Antialias": "enabled", "Xft/Hinting": "hinting" }.items(): if prop_name in d: value_type, value = d.get(prop_name) if value_type == XSettingsTypeInteger and value > 0: info[name] = bool(value) def get_contrast(value): #win32 API uses numerical values: #(this is my best guess at translating the X11 names) return { "hintnone": 0, "hintslight": 1000, "hintmedium": 1600, "hintfull": 2200 }.get(bytestostr(value)) for prop_name, name, convert in (("Xft/HintStyle", "hintstyle", bytestostr), ("Xft/HintStyle", "contrast", get_contrast), ("Xft/RGBA", "orientation", lambda x: bytestostr(x).upper())): if prop_name in d: value_type, value = d.get(prop_name) if value_type == XSettingsTypeString: cval = convert(value) if cval is not None: info[name] = cval except Exception as e: screenlog.warn("failed to get antialias info from xsettings: %s", e) screenlog("get_antialias_info()=%s", info) return info
def setup_printer(self, name, props, attributes): from xpra.platform.pycups_printing import add_printer props = typedict(props) info = props.strget("printer-info", "") attrs = attributes.copy() attrs["remote-printer"] = name attrs["remote-device-uri"] = props.strget("device-uri") location = PRINTER_LOCATION_STRING if self.hostname: location = "on %s" if PRINTER_LOCATION_STRING: #ie: on FOO (via xpra) location = "on %s (%s)" % (self.hostname, PRINTER_LOCATION_STRING) try: printer = printer_name(name) def printer_added(): #once the printer has been added, register it in the list #(so it will be removed on exit) log.info("the remote printer '%s' has been configured", printer) self.printers[name] = props self.printers_added.add(name) add_printer(printer, props, info, location, attrs, success_cb=printer_added) except Exception as e: log.warn("Warning: failed to add virtual printer '%s'", bytestostr(name)) log.warn(" %s", e) log("setup_printer(%s, %s, %s)", name, props, attributes, exc_info=True)
def process_packet(self, proto, packet): command = bytestostr(packet[0]) if command == Protocol.CONNECTION_LOST: log("connection-lost: %s, calling stop", packet[1:]) self.net_stop() return elif command == Protocol.GIBBERISH: log.warn("gibberish received:") log.warn(" %s", repr_ellipsized(packet[1], limit=80)) log.warn(" stopping") self.net_stop() return elif command == "stop": log("received stop message") self.net_stop() return elif command == "exit": log("received exit message") sys.exit(0) return #make it easier to hookup signals to methods: attr = command.replace("-", "_") if self.method_whitelist is not None and attr not in self.method_whitelist: log.warn("invalid command: %s (not in whitelist: %s)", attr, self.method_whitelist) return wo = self.wrapped_object if not wo: log("wrapped object is no more, ignoring method call '%s'", attr) return method = getattr(wo, attr, None) if not method: log.warn("unknown command: '%s'", attr) log.warn(" packet: '%s'", repr_ellipsized(str(packet))) return if DEBUG_WRAPPER: log("calling %s.%s%s", wo, attr, str(tuple(packet[1:]))[:128]) self.idle_add(method, *packet[1:]) INJECT_FAULT(proto)
def get_nvml_driver_version(): try: from pynvml import nvmlInit, nvmlShutdown, nvmlSystemGetDriverVersion except ImportError as e: log("cannot use nvml to query the kernel module version:") log(" %s", e) else: try: if wrap_nvml_init(nvmlInit): try: v = nvmlSystemGetDriverVersion() finally: nvmlShutdown() log("nvmlSystemGetDriverVersion=%s", bytestostr(v)) return v.split(b".") except Exception as e: log("get_nvml_driver_version() pynvml error", exc_info=True) log.warn( "Warning: failed to query the NVidia kernel module version using NVML:" ) log.warn(" %s", e) return ()
def _handle_property_change(self, name): #ie: _handle_property_change("_NET_WM_NAME") metalog("Property changed on %#x: %s", self.xid, name) x11proptype = X11_PROPERTIES_DEBUG.get(name) if x11proptype is not None: metalog.info("%s=%s", name, self.prop_get(name, x11proptype, True, False)) if name in PROPERTIES_IGNORED: return if X11PROPERTY_SYNC and not any( name.startswith(x) for x in X11PROPERTY_SYNC_BLACKLIST): try: with xsync: prop_type = prop_type_get(self.client_window, name) metalog("_handle_property_change(%s) property type=%s", name, prop_type) if prop_type: dtype, dformat = prop_type ptype = PYTHON_TYPES.get(bytestostr(dtype)) if ptype: value = self.prop_get(name, ptype) metalog("_handle_property_change(%s) value=%s", name, value) self.emit("x11-property-changed", (name, ptype, dformat, value)) return except Exception: metalog("_handle_property_change(%s)", name, exc_info=True) self.emit("x11-property-changed", (name, "", 0, "")) handler = self._x11_property_handlers.get(name) if handler: try: with xsync: handler(self) except XError as e: log("_handle_property_change", exc_info=True) log.error("Error processing property change for '%s'", name) log.error(" on window %#x", self.xid) log.error(" %s", e)
def populate_table(self): if self.table: self.alignment.remove(self.table) #remove expired requests: now = monotonic() self.requests = [x for x in self.requests if x[-1]>now] self.expire_labels = {} tb = TableBuilder(rows=1, columns=4, row_spacings=15) #generate a new table: self.table = tb.get_table() def l(s=""): return Gtk.Label(label=s) if not self.requests: tb.add_row(l("No requests pending")) else: headers = [l("URL / Filename"), l(), l("Expires in"), l("Action")] tb.add_row(*headers) for cb_answer, send_id, dtype, url, filesize, printit, openit, expires in self.requests: details = "" if dtype=="file" and filesize>0: details = "%sB" % std_unit_dec(filesize) expires_label = l() self.expire_labels[send_id] = (expires_label, expires) buttons = self.action_buttons(cb_answer, send_id, dtype, printit, openit) s = bytestostr(url) main_label = l(s) if dtype=="url" and s.find("?")>0 and len(s)>48: parts = s.split("?", 1) main_label.set_label(parts[0]+"?..") main_label.set_tooltip_text(s) main_label.set_line_wrap(True) main_label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) main_label.set_size_request(URI_MAX_WIDTH, -1) main_label.set_selectable(True) items = (main_label, l(details), expires_label, buttons) tb.add_row(*items) self.update_expires_label() self.alignment.add(self.table) self.table.show_all()
def _process_send_data_response(self, packet): send_id, accept = packet[1:3] filelog("process send-data-response: send_id=%s, accept=%s", s(send_id), accept) send_id = s(send_id) timer = self.pending_send_data_timers.pop(send_id, None) if timer: self.source_remove(timer) v = self.pending_send_data.pop(send_id, None) if v is None: filelog.warn("Warning: cannot find send-file entry") return dtype = v[0] url = v[1] if accept == DENY: filelog.info("the request to send %s '%s' has been denied", bytestostr(dtype), s(url)) return assert accept in ( ACCEPT, OPEN), "unknown value for send-data response: %s" % (accept, ) if dtype == b"file": mimetype, data, filesize, printit, openit, options = v[2:] if accept == ACCEPT: self.do_send_file(url, mimetype, data, filesize, printit, openit, options, send_id) else: assert openit and accept == OPEN #try to open at this end: self._open_file(url) elif dtype == b"url": if accept == ACCEPT: self.do_send_open_url(url, send_id) else: assert accept == OPEN #open it at this end: self._open_url(url) else: filelog.error("Error: unknown datatype '%s'", dtype)
def set_selection_response(self, requestor, target, prop, dtype, dformat, data, time=0): log("set_selection_response(%s, %s, %s, %s, %s, %r, %i)", requestor, target, prop, dtype, dformat, repr_ellipsized(bytestostr(data)), time) #answer the selection request: with xsync: xid = get_xwindow(requestor) if data is not None: X11Window.XChangeProperty(xid, prop, dtype, dformat, data) else: #maybe even delete the property? #X11Window.XDeleteProperty(xid, prop) prop = None X11Window.sendSelectionNotify(xid, self._selection, target, prop, time)
def get_printers(): global PRINTER_ENUMS, PRINTER_ENUM_VALUES, SKIPPED_PRINTERS, PRINTER_LEVEL printers = {} for penum in PRINTER_ENUMS: try: eprinters = [] enum_values = [PRINTER_ENUM_VALUES.get(x, 0) for x in penum] enum_val = sum(enum_values) log("enum(%s)=%s=%s", penum, "+".join(str(x) for x in enum_values), enum_val) assert enum_val is not None, "invalid printer enum %s" % penum log("querying %s printers with level=%s", penum, PRINTER_LEVEL) for p in EnumPrinters(enum_val, None, PRINTER_LEVEL): flags, desc, name, comment = p if name in SKIPPED_PRINTERS: log("skipped printer: %#x, %s, %s, %s", flags, desc, name, comment) continue if name in printers: log("skipped duplicate printer: %#x, %s, %s, %s", flags, desc, name, comment) continue log("found printer: %#x, %s, %s, %s", flags, desc, name, comment) #strip duplicated and empty strings from the description: desc_els = [] for x in desc.split(","): if x and not desc_els.count(x): desc_els.append(x) info = {"printer-info" : bytestostr(",".join(desc_els)), "type" : penum} if comment: info["printer-make-and-model"] = comment printers[name] = info eprinters.append(name) log("%s printers: %s", penum, eprinters) except Exception as e: log.warn("Warning: failed to query %s printers:", penum) log.warn(" %s", e) log("query error", exc_info=True) del e log("win32.get_printers()=%s", printers) return printers
def _process_challenge(self, packet): authlog("processing challenge: %s", packet[1:]) if not self.validate_challenge_packet(packet): return authlog("challenge handlers: %s", self.challenge_handlers) digest = bytestostr(packet[3]) while self.challenge_handlers: handler = self.pop_challenge_handler(digest) try: authlog("calling challenge handler %s", handler) r = handler.handle(packet) authlog("%s(%s)=%s", handler.handle, packet, r) if r: #the challenge handler claims to have handled authentication return except Exception as e: authlog("%s(%s)", handler.handle, packet, exc_info=True) authlog.error("Error in %r challenge handler:", handler) authlog.error(" %s", str(e) or type(e)) continue authlog.warn("Warning: failed to connect, authentication required") self.quit(EXIT_PASSWORD_REQUIRED)
def _process_clipboard_token(self, packet): selection = bytestostr(packet[1]) name = self.remote_to_local(selection) proxy = self._clipboard_proxies.get(name) if proxy is None: #this can happen if the server has fewer clipboards than the client, #ie: with win32 shadow servers l = log if name in ALL_CLIPBOARDS: l = log.warn l("ignoring token for clipboard proxy name '%s' (no proxy)", name) return if not proxy.is_enabled(): log.warn("ignoring token for clipboard proxy name '%s' (disabled)", name) return log( "process clipboard token selection=%s, local clipboard name=%s, proxy=%s", selection, name, proxy) targets = None target_data = None if proxy._can_receive: if len(packet) >= 3: targets = packet[2] if len(packet) >= 8: target, dtype, dformat, wire_encoding, wire_data = packet[3:8] raw_data = self._munge_wire_selection_to_raw( wire_encoding, dtype, dformat, wire_data) target_data = {target: raw_data} #older versions always claimed the selection when the token is received: claim = True if len(packet) >= 10: claim = bool(packet[8]) #clients can now also change the greedy flag on the fly, #this is needed for clipboard direction restrictions: #the client may want to be notified of clipboard changes, just like a greedy client proxy._greedy_client = bool(packet[9]) synchronous_client = len(packet) >= 11 and bool(packet[10]) proxy.got_token(targets, target_data, claim, synchronous_client)
def process_packet(self, _proto, packet): try: handler = None packet_type = packet[0] if packet_type != int: packet_type = bytestostr(packet_type) may_log_packet(packet_type, packet) handler = self._packet_handlers.get(packet_type) if handler: handler(packet) return handler = self._ui_packet_handlers.get(packet_type) if not handler: netlog.error("unknown packet type: %s", packet_type) return self.idle_add(handler, packet) except Exception: netlog.error( "Unhandled error while processing a '%s' packet from peer using %s", packet_type, handler, exc_info=True)
def do_process_control_packet(self, proto, packet): log("process_control_packet(%s, %s)", proto, packet) packet_type = bytestostr(packet[0]) if packet_type==CONNECTION_LOST: log.info("Connection lost") if proto in self.potential_protocols: self.potential_protocols.remove(proto) return if packet_type=="hello": caps = typedict(packet[1]) if caps.boolget("challenge"): self.send_disconnect(proto, AUTHENTICATION_ERROR, "this socket does not use authentication") return generic_request = caps.strget("request") def is_req(mode): return generic_request==mode or caps.boolget("%s_request" % mode) if is_req("info"): info = self.get_proxy_info(proto) info.setdefault("connection", {}).update(self.get_connection_info()) proto.send_now(("hello", info)) self.timeout_add(5*1000, self.send_disconnect, proto, CLIENT_EXIT_TIMEOUT, "info sent") return if is_req("stop"): self.stop(None, "socket request") return if is_req("version"): version = XPRA_VERSION if caps.boolget("full-version-request"): version = full_version_str() proto.send_now(("hello", {"version" : version})) self.timeout_add(5*1000, self.send_disconnect, proto, CLIENT_EXIT_TIMEOUT, "version sent") return log.warn("Warning: invalid hello packet,") log.warn(" not a supported control channel request") else: log.warn("Warning: invalid packet type for control channel") log.warn(" '%s' is not supported, only 'hello' is", packet_type) self.send_disconnect(proto, CONTROL_COMMAND_ERROR, "this socket only handles 'info', 'version' and 'stop' requests")
def _process_send_data_request(self, packet): dtype, send_id, url, _, filesize, printit, openit = packet[1:8] filelog("process send-data-request: send_id=%s, url=%s, printit=%s, openit=%s", s(send_id), url, printit, openit) def cb_answer(accept): filelog("accept%s=%s", (url, printit, openit), accept) self.send("send-data-response", send_id, accept) #filenames and url are always sent encoded as utf8: try: url = strtobytes(url).decode("utf8") except: url = bytestostr(url) if dtype==b"file": if not self.file_transfer: cb_answer(False) return url = os.path.basename(url) if printit: ask = self.printing_ask elif openit: ask = self.file_transfer_ask or self.open_files_ask else: ask = self.file_transfer_ask elif dtype==b"url": if not self.open_url: cb_answer(False) return ask = self.open_url_ask else: filelog.warn("Warning: unknown data request type '%s'", dtype) cb_answer(False) return if not ask: filelog.warn("Warning: received a send-data request for a %s,", dtype) filelog.warn(" but authorization is not required by the client") #fail it because if we responded with True, #it would fail later when we don't find this send_id in our accepted list cb_answer(False) else: self.ask_data_request(cb_answer, send_id, dtype, url, filesize, printit, openit)
def process_downloaded_file(self, filename, mimetype, printit, openit, filesize, options): filelog.info("downloaded %s bytes to %s file%s:", filesize, (mimetype or "temporary"), ["", " for printing"][int(printit)]) filelog.info(" '%s'", filename) #some file requests may have a custom callback #(ie: bug report tool will just include the file) rf = options.tupleget("request-file") if rf and len(rf) >= 2: argf = rf[0] cb = self.file_request_callback.pop(bytestostr(argf), None) if cb: cb(filename, filesize) return if printit or openit: t = start_thread(self.do_process_downloaded_file, "process-download", daemon=False, args=(filename, mimetype, printit, openit, filesize, options)) filelog("started process-download thread: %s", t)
def do_command(self): if self.server_capabilities: if FLATTEN_INFO < 2: #compatibility mode: for k in sorted_nicely(self.server_capabilities.keys()): v = self.server_capabilities.get(k) if sys.version_info[0] >= 3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only def fixvalue(w): if type(w) == bytes: return bytestostr(w) elif type(w) in (tuple, list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) log.info("%s=%s", bytestostr(k), nonl(v)) else: print_nested_dict(self.server_capabilities) self.quit(EXIT_OK)
def process_packet(self, proto, packet): command = bytestostr(packet[0]) if command==Protocol.CONNECTION_LOST: log("connection-lost: %s, calling stop", packet[1:]) self.net_stop() return elif command==Protocol.GIBBERISH: log.warn("gibberish received:") log.warn(" %s", repr_ellipsized(packet[1], limit=80)) log.warn(" stopping") self.net_stop() return elif command=="stop": log("received stop message") self.net_stop() return elif command=="exit": log("received exit message") sys.exit(0) return #make it easier to hookup signals to methods: attr = command.replace("-", "_") if self.method_whitelist is not None and attr not in self.method_whitelist: log.warn("invalid command: %s (not in whitelist: %s)", attr, self.method_whitelist) return wo = self.wrapped_object if not wo: log("wrapped object is no more, ignoring method call '%s'", attr) return method = getattr(wo, attr, None) if not method: log.warn("unknown command: '%s'", attr) log.warn(" packet: '%s'", repr_ellipsized(str(packet))) return if DEBUG_WRAPPER: log("calling %s.%s%s", wo, attr, str(tuple(packet[1:]))[:128]) self.idle_add(method, *packet[1:]) INJECT_FAULT(proto)
def get_pulse_defaults(device_name_match=None, want_monitor_device=True, input_or_output=None, remote=None, env_device_name=None): try: device = get_pulse_device(device_name_match, want_monitor_device, input_or_output, remote, env_device_name) except Exception as e: log("get_pulse_defaults%s", (device_name_match, want_monitor_device, input_or_output, remote, env_device_name), exc_info=True) log.warn("Warning: failed to identify the pulseaudio default device to use") log.warn(" %s", e) return {} if not device: return {} #make sure it is not muted: try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, set_source_mute, set_sink_mute if has_pa(): if input_or_output is True or want_monitor_device: set_source_mute(device, mute=False) elif input_or_output is False: set_sink_mute(device, mute=False) except Exception as e: log("device %s may still be muted: %s", device, e) return {"device" : bytestostr(device)}
def get_remote_lib_versions(c: typedict, libs=( "glib", "gobject", "gtk", "gdk", "cairo", "pango", "sound.gst", "sound.pygst", "python", )): versions = {} for x in libs: v = c.get("%s.version" % x, None) if v is None: #fallback to structured access: d = c.get(x, None) if isinstance(d, dict): v = typedict(d).get("version", None) if v: versions[x] = bytestostr(v) return versions
def save_input_conf(xorg_conf_dir, i, dev_type, device_uuid, uid, gid): upper_dev_type = dev_type[:1].upper() + dev_type[1:] #ie: Pointer product_name = "Xpra Virtual %s %s" % (upper_dev_type, bytestostr(device_uuid)) identifier = "xpra-virtual-%s" % dev_type conf_file = os.path.join(xorg_conf_dir, "%02i-%s.conf" % (i, dev_type)) with open(conf_file, "wb") as f: f.write( strtobytes("""Section "InputClass" Identifier "%s" MatchProduct "%s" MatchUSBID "ffff:ffff" MatchIs%s "True" Driver "libinput" Option "AccelProfile" "flat" Option "Ignore" "False" EndSection """ % (identifier, product_name, upper_dev_type))) os.fchown(f.fileno(), uid, gid) #Option "AccelerationProfile" "-1" #Option "AccelerationScheme" "none" #Option "AccelSpeed" "-1" return conf_file
def draw_region(self, x, y, width, height, coding, img_data, rowstride, options, callbacks): """ dispatches the paint to one of the paint_XXXX methods """ log("draw_region(%s, %s, %s, %s, %s, %s bytes, %s, %s, %s)", x, y, width, height, coding, len(img_data), rowstride, options, callbacks) img_data = self.img_data_tobytes(img_data) coding = bytestostr(coding) if coding == "mmap": self.idle_add(self.paint_mmap, img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb24": if rowstride==0: rowstride = width * 3 self.paint_rgb24(img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb32": if rowstride==0: rowstride = width * 4 self.paint_rgb32(img_data, x, y, width, height, rowstride, options, callbacks) elif coding in VIDEO_DECODERS: self.paint_with_video_decoder(VIDEO_DECODERS.get(coding), coding, img_data, x, y, width, height, options, callbacks) elif coding == "webp": self.paint_webp(img_data, x, y, width, height, options, callbacks) elif coding in self._PIL_encodings: self.paint_image(coding, img_data, x, y, width, height, options, callbacks) else: self.do_draw_region(x, y, width, height, coding, img_data, rowstride, options, callbacks)
def process_packet(self, proto, packet): try: handler = None packet_type = packet[0] if packet_type != int: packet_type = bytestostr(packet_type) handler = self._packet_handlers.get(packet_type) if handler: handler(packet) return handler = self._ui_packet_handlers.get(packet_type) if not handler: log.error("unknown packet type: %s", packet_type) return self.idle_add(handler, packet) except KeyboardInterrupt: raise except: log.error( "Unhandled error while processing a '%s' packet from peer using %s", packet_type, handler, exc_info=True)
def get_session_info(self, sockpath): #the lazy way using a subprocess if WIN32: socktype = "namedpipe" else: socktype = "socket" cmd = get_nodock_command() + ["id", "%s:%s" % (socktype, sockpath)] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = p.communicate()[0] log("get_sessions_info(%s) returncode(%s)=%s", sockpath, cmd, p.returncode) if p.returncode != 0: return None out = bytestostr(stdout) info = {} for line in out.splitlines(): parts = line.split("=", 1) if len(parts) == 2: info[parts[0]] = parts[1] log("get_sessions_info(%s)=%s", sockpath, info) return info
def process_packet(self, proto, packet): command = bytestostr(packet[0]) if command==Protocol.CONNECTION_LOST: log("connection-lost: %s, calling stop", packet[1:]) self.net_stop() return elif command==Protocol.GIBBERISH: log("gibberish received: %s", repr_ellipsized(packet)) self.net_stop() return #make it easier to hookup signals to methods: attr = command.replace("-", "_") if self.method_whitelist is not None and attr not in self.method_whitelist: log.warn("invalid command: %s (not in whitelist: %s)", attr, self.method_whitelist) return method = getattr(self.wrapped_object, attr, None) if not method: if self.wrapped_object is not None: log.warn("unknown command: %s", command) return if DEBUG_WRAPPER: log("calling %s.%s%s", self.wrapped_object, attr, str(tuple(packet[1:]))[:128]) gobject.idle_add(method, *packet[1:])
def get_owner_info(owner, our_window): if not owner: return "unknown" if owner == our_window: return "our window (hwnd=%#x)" % our_window pid = DWORD(0) GetWindowThreadProcessId(owner, byref(pid)) if not pid: return "unknown (hwnd=%#x)" % owner #log("get_owner_info(%#x) pid=%s", owner, pid.value) proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid) if not proc_handle: return "pid %i (hwnd=%#x)" % (pid.value, owner) try: size = DWORD(256) process_name = create_string_buffer(size.value + 1) if not QueryFullProcessImageNameA(proc_handle, 0, process_name, byref(size)): return "pid %i" % pid.value return "'%s' with pid %s (hwnd=%#x)" % (bytestostr( process_name.value), pid.value, owner) finally: CloseHandle(proc_handle)
def _process_ack_file_chunk(self, packet): #the other end received our send-file or send-file-chunk, #send some more file data filelog("ack-file-chunk: %s", packet[1:]) chunk_id, state, error_message, chunk = packet[1:5] chunk_id = bytestostr(chunk_id) if not state: filelog.error("Error: remote end is cancelling the file transfer:") filelog.error(" %s", error_message) del self.send_chunks_in_progress[chunk_id] return chunk_state = self.send_chunks_in_progress.get(chunk_id) if not chunk_state: filelog.error("Error: cannot find the file transfer id '%s'", nonl(chunk_id)) return if chunk_state[-1]!=chunk: filelog.error("Error: chunk number mismatch (%i vs %i)", chunk_state, chunk) del self.send_chunks_in_progress[chunk_id] return start_time, data, chunk_size, timer, chunk = chunk_state if not data: #all sent! elapsed = monotonic_time()-start_time filelog("%i chunks of %i bytes sent in %ims (%sB/s)", chunk, chunk_size, elapsed*1000, std_unit(chunk*chunk_size/elapsed)) del self.send_chunks_in_progress[chunk_id] return assert chunk_size>0 #carve out another chunk: cdata = self.compressed_wrapper("file-data", data[:chunk_size]) data = data[chunk_size:] chunk += 1 if timer: self.source_remove(timer) timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_sending, chunk_id, chunk) self.send_chunks_in_progress[chunk_id] = [start_time, data, chunk_size, timer, chunk] self.send("send-file-chunk", chunk_id, chunk, cdata, bool(data))
def start_dbus(dbus_launch): if not dbus_launch or dbus_launch.lower() in FALSE_OPTIONS: return 0, {} try: def preexec(): assert POSIX os.setsid() close_fds() proc = Popen(dbus_launch, stdin=PIPE, stdout=PIPE, shell=True, preexec_fn=preexec) out = proc.communicate()[0] assert proc.poll() == 0, "exit code is %s" % proc.poll() #parse and add to global env: dbus_env = {} for l in bytestostr(out).splitlines(): parts = l.split("=", 1) if len(parts) != 2: continue k, v = parts if v.startswith("'") and v.endswith("';"): v = v[1:-2] dbus_env[k] = v dbus_pid = int(dbus_env.get("DBUS_SESSION_BUS_PID", 0)) return dbus_pid, dbus_env except Exception as e: from xpra.log import Logger log = Logger("dbus") log.debug("start_dbus(%s)", dbus_launch, exc_info=True) error("dbus-launch failed to start using command '%s':\n" % dbus_launch) error(" %s\n" % e) return 0, {}
def _process_request_file(self, proto, packet): ss = self.get_server_source(proto) if not ss: printlog.warn( "Warning: invalid client source for send-data-response packet") return try: argf = packet[1].decode("utf-8") except UnicodeDecodeError: argf = bytestostr(packet[1]) openit = packet[2] filename = os.path.abspath(osexpand(argf)) if not os.path.exists(filename): filelog.warn("Warning: the file requested does not exist:") filelog.warn(" %s", filename) ss.may_notify(XPRA_FILETRANSFER_NOTIFICATION_ID, "File not found", "The file requested does not exist:\n%s" % filename, icon_name="file") return try: stat = os.stat(filename) filelog("os.stat(%s)=%s", filename, stat) except os.error: filelog("os.stat(%s)", filename, exc_info=True) else: file_size_MB = stat.st_size // 1024 // 1024 if file_size_MB > self.file_transfer.file_size_limit or file_size_MB > ss.file_size_limit: ss.may_notify( XPRA_FILETRANSFER_NOTIFICATION_ID, "File too large", "The file requested is too large to send:\n%s\nis %iMB" % (argf, file_size_MB), icon_name="file") return data = load_binary_file(filename) ss.send_file(filename, "", data, len(data), openit=openit)
def listget(self, k, default_value=[], item_type=None, max_items=None): v = self.capsget(k, default_value) if v is None: return default_value assert type(v) in ( list, tuple ), "expected a list or tuple value for %s but got %s" % (k, type(v)) aslist = list(v) if item_type: for i in range(len(aslist)): x = aslist[i] if sys.version > '3' and type(x) == bytes and item_type == str: x = bytestostr(x) aslist[i] = x assert type( x ) == item_type, "invalid item type for %s %s: expected %s but got %s" % ( type(v), k, item_type, type(x)) if max_items is not None: assert len( v ) <= max_items, "too many items in %s %s: maximum %s allowed, but got %s" % ( type(v), k, max_items, len(v)) return aslist
def draw_region(self, x, y, width, height, coding, img_data, rowstride, options, callbacks): """ dispatches the paint to one of the paint_XXXX methods """ if DRAW_DEBUG: log.info("draw_region(%s, %s, %s, %s, %s, %s bytes, %s, %s, %s)", x, y, width, height, coding, len(img_data), rowstride, options, callbacks) coding = bytestostr(coding) if coding == "mmap": self.idle_add(self.paint_mmap, img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb24": if rowstride==0: rowstride = width * 3 self.paint_rgb24(img_data, x, y, width, height, rowstride, options, callbacks) elif coding == "rgb32": if rowstride==0: rowstride = width * 4 self.paint_rgb32(img_data, x, y, width, height, rowstride, options, callbacks) elif coding in ("vp8", "vp9", "h264"): assert coding in VIDEO_DECODERS, "no %s decoder available" % coding self.paint_with_video_decoder(VIDEO_DECODERS.get(coding), coding, img_data, x, y, width, height, options, callbacks) elif coding == "webp": self.paint_webp(img_data, x, y, width, height, options, callbacks) elif coding[:3]=="png" or coding=="jpeg": self.paint_image(coding, img_data, x, y, width, height, options, callbacks) else: raise Exception("invalid encoding: %s" % coding)
def _cmp(o, r): #our own deep compare function, #ignores tuple vs list differences, #and gives us a clue about where the problem is if type(o)==type(r) and o==r: return if type(r) in (tuple, list) and type(o) in (tuple, list): assert len(r)==len(o), "list/tuple differs in length: expected %s but got %s" % (o, r) for i in range(len(r)): _cmp(o[i], r[i]) return if type(r)==dict and type(o)==dict: for k,ov in o.items(): #with py3k, the key can end up being bytes instead of string... rv = r.get(k, r.get(bytestostr(k), r.get(strtobytes(k)))) assert rv is not None, "restored dict is missing %s: %s" % (k, r) _cmp(ov, rv) return import sys if sys.version_info[0]<3 and type(o)==unicode and type(r)==str: o = o.encode("utf-8") elif type(o)==bytes and type(r)==str: o = o.decode("utf-8") elif type(o)==str and type(r)==bytes: r = r.decode("utf-8") if o==r: return print("") print("original %s:" % type(o)) print("returned %s:" % type(r)) try: print("original: %s" % binascii.hexlify(str(o))) print("returned: %s" % binascii.hexlify(str(r))) except: pass assert False, "value does not match: expected %s (%s) but got %s (%s)" % (o, type(o), r, type(r))
def _process_command_signal(self, _proto, packet): pid = packet[1] signame = bytestostr(packet[2]) if signame not in COMMAND_SIGNALS: log.warn("Warning: invalid signal received: '%s'", signame) return procinfo = self.child_reaper.get_proc_info(pid) if not procinfo: log.warn("Warning: command not found for pid %i", pid) return if procinfo.returncode is not None: log.warn("Warning: command for pid %i has already terminated", pid) return import signal sigval = getattr(signal, signame, None) if not sigval: log.error("Error: signal '%s' not found!", signame) return log.info("sending signal %s to pid %i", signame, pid) try: os.kill(pid, sigval) except Exception as e: log.error("Error sending signal '%s' to pid %i", signame, pid) log.error(" %s", e)
def _munge_raw_selection_to_wire(self, target, dtype, dformat, data): log("_munge_raw_selection_to_wire%s", (target, dtype, dformat, repr_ellipsized(bytestostr(data)))) # Some types just cannot be marshalled: if dtype in ("WINDOW", "PIXMAP", "BITMAP", "DRAWABLE", "PIXEL", "COLORMAP"): log("skipping clipboard data of type: %s, format=%s, len(data)=%s", dtype, dformat, len(data or b"")) return None, None if target == "TARGETS" and dtype == "ATOM" and isinstance( data, (tuple, list)): #targets is special cased here #because we can get the values in wire format already (not atoms) #thanks to the request_targets() function (required on win32) return "atoms", _filter_targets(data) try: return self._do_munge_raw_selection_to_wire( target, dtype, dformat, data) except Exception: log.error("Error: failed to convert selection data to wire format") log.error(" target was %s", target) log.error(" dtype=%s, dformat=%s, data=%s (%s)", dtype, dformat, repr_ellipsized(str(data)), type(data)) raise
def strget(self, k, default=None): v = self.capsget(k, default) if v is None: return None return bytestostr(v)
def populate_microphone_info(*args): can = scaps.boolget("sound.receive", False) and self.client.microphone_allowed self.bool_icon(self.server_microphone_icon, can) self.microphone_codec_label.set_text(bytestostr(pipeline_info(can, self.client.sound_source)))
def populate_statistics(self): log("populate_statistics()") if time.time()-self.last_populate_statistics<1.0: #don't repopulate more than every second return True self.last_populate_statistics = time.time() if self.client.server_info_request: self.client.send_info_request() def setall(labels, values): assert len(labels)==len(values), "%s labels and %s values (%s vs %s)" % (len(labels), len(values), labels, values) for i in range(len(labels)): l = labels[i] v = values[i] l.set_text(str(v)) def setlabels(labels, values, rounding=int): if len(values)==0: return avg = sum(values)/len(values) svalues = sorted(values) l = len(svalues) assert l>0 if l<10: index = l-1 else: index = int(l*90/100) index = max(0, min(l-1, index)) pct = svalues[index] disp = values[-1], min(values), avg, pct, max(values) rounded_values = [rounding(v) for v in disp] setall(labels, rounded_values) if len(self.client.server_ping_latency)>0: spl = [1000.0*x for _,x in list(self.client.server_ping_latency)] setlabels(self.server_latency_labels, spl) if len(self.client.client_ping_latency)>0: cpl = [1000.0*x for _,x in list(self.client.client_ping_latency)] setlabels(self.client_latency_labels, cpl) if self.client.windows_enabled: if self.client.server_info_request: setall(self.batch_labels, self.values_from_info("batch_delay", "batch.delay")) setall(self.damage_labels, self.values_from_info("damage_out_latency", "damage.out_latency")) setall(self.quality_labels, self.all_values_from_info("quality", "encoding.quality")) setall(self.speed_labels, self.all_values_from_info("speed", "encoding.speed")) region_sizes = [] rps = [] pps = [] decoding_latency = [] if len(self.client.pixel_counter)>0: min_time = None max_time = None regions_per_second = {} pixels_per_second = {} for start_time, end_time, size in self.client.pixel_counter: decoding_latency.append(int(1000.0*(end_time-start_time))) region_sizes.append(size) if min_time is None or min_time>end_time: min_time = end_time if max_time is None or max_time<end_time: max_time = end_time time_in_seconds = int(end_time) regions = regions_per_second.get(time_in_seconds, 0) regions_per_second[time_in_seconds] = regions+1 pixels = pixels_per_second.get(time_in_seconds, 0) pixels_per_second[time_in_seconds] = pixels + size if int(min_time)+1 < int(max_time): for t in range(int(min_time)+1, int(max_time)): rps.append(regions_per_second.get(t, 0)) pps.append(pixels_per_second.get(t, 0)) setlabels(self.decoding_labels, decoding_latency) setlabels(self.regions_per_second_labels, rps) setlabels(self.regions_sizes_labels, region_sizes, rounding=std_unit_dec) setlabels(self.pixels_per_second_labels, pps, rounding=std_unit_dec) windows, gl, transient, trays = 0, 0, 0, 0 for w in self.client._window_to_id.keys(): if w.is_tray(): trays += 1 elif w.is_OR(): transient +=1 else: windows += 1 if w.is_GL(): gl += 1 self.windows_managed_label.set_text(str(windows)) self.transient_managed_label.set_text(str(transient)) self.trays_managed_label.set_text(str(trays)) if self.client.client_supports_opengl: self.opengl_label.set_text(str(gl)) #remove all the current labels: for x in self.encoder_info_box.get_children(): self.encoder_info_box.remove(x) window_encoder_stats = {} if self.client.server_last_info: #We are interested in data like: #window[1].encoder=x264 #window[1].encoder.frames=1 for k,v in self.client.server_last_info.items(): k = bytestostr(k) pos = k.find("].encoder") if k.startswith("window[") and pos>0: wid_str = k[len("window["):pos] #ie: "1" ekey = k[(pos+len("].encoder")):] #ie: "" or ".frames" if ekey.startswith("."): ekey = ekey[1:] try: wid = int(wid_str) props = window_encoder_stats.setdefault(wid, {}) props[ekey] = v except: #wid_str may be invalid, ie: #window[1].pipeline_option[1].encoder=codec_spec(xpra.codecs.enc_x264.encoder.Encoder) # -> wid_str= "1].pipeline_option[1" pass #print("window_encoder_stats=%s" % window_encoder_stats) for wid, props in window_encoder_stats.items(): l = label("%s (%s)" % (wid, bytestostr(props.get("")))) l.show() info = ["%s=%s" % (k,v) for k,v in props.items() if k!=""] l.set_tooltip_text(" ".join(info)) self.encoder_info_box.add(l) return True
def san(v): if type(v)==int: return v return bytestostr(v)
def capsget(self, capabilities, key, default): v = capabilities.get(strtobytes(key), default) if sys.version >= '3' and type(v)==bytes: v = bytestostr(v) return v
def process_packet(self, proto, packet): if DEBUG_WRAPPER: log("process_packet(%s, %s)", proto, [str(x)[:32] for x in packet]) signal_name = bytestostr(packet[0]) self._fire_callback(signal_name, packet[1:]) INJECT_FAULT(proto)