def parse_auth_line(line): ldata = line.split(b"|") log("found %s fields", len(ldata)) assert len(ldata) >= 4, "not enough fields" #parse fields: username = ldata[0] password = ldata[1] def getsysid(s, get_default_value): if s: try: return int(s) except: pass return get_default_value() uid = getsysid(ldata[2], os.getuid) gid = getsysid(ldata[3], os.getgid) displays = ldata[4].split(b",") env_options = {} session_options = {} if len(ldata) >= 6: env_options = parse_simple_dict(ldata[5], ";") if len(ldata) >= 7: session_options = parse_simple_dict(ldata[6], ";") return username, password, uid, gid, displays, env_options, session_options
def get_sessions(self): import sqlite3 try: conn = sqlite3.connect(self.filename) conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute(self.sessions_query, [self.username, self.password_used or ""]) data = cursor.fetchone() except sqlite3.DatabaseError as e: log("get_sessions()", exc_info=True) log.error("Error: sqlauth database access problem:") log.error(" %s", e) return None try: uid = parse_uid(data["uid"]) gid = parse_gid(data["gid"]) displays = [] env_options = {} session_options = {} if data["displays"]: displays = [x.strip() for x in str(data[2]).split(",")] if data["env_options"]: env_options = parse_simple_dict(str(data[3]), ";") if data["session_options"]: session_options = parse_simple_dict(str(data[4]), ";") except Exception as e: log("get_sessions() error on row %s", data, exc_info=True) log.error("Error: sqlauth database row parsing problem:") log.error(" %s", e) return None return uid, gid, displays, env_options, session_options
def get_sound_source_options(plugin, options_str, device, want_monitor_device, remote): """ Given a plugin (short name), options string and remote info, return the options for the plugin given, using the dynamic defaults (which may use remote info) and applying the options string on top. """ #ie: get_sound_source_options("audiotestsrc", "wave=4,freq=220", {remote_pulseaudio_server=XYZ}): #use the defaults as starting point: defaults_fn = DEFAULT_SRC_PLUGIN_OPTIONS.get(plugin) if defaults_fn: options = defaults_fn(device, want_monitor_device, remote) if options is None: #means failure return None else: options = {} #if we add support for choosing devices in the GUI, #this code will then get used: if device and plugin in SRC_HAS_DEVICE_NAME: #assume the user knows the "device-name"... #(since I have no idea where to get the "device" string) options["device-name"] = device options.update(parse_simple_dict(options_str)) return options
def parse_bind_ip(bind_ip, default_port=DEFAULT_PORT): ip_sockets = {} if bind_ip: for spec in bind_ip: parts = spec.split(",", 1) ip_port = parts[0] if ":" not in spec: raise InitException("port must be specified as [HOST]:PORT") host, port = ip_port.rsplit(":", 1) if host == "": host = "127.0.0.1" if not port: iport = default_port elif port == "0": iport = 0 else: try: iport = int(port) assert 0 < iport < 2**16 except (TypeError, ValueError): raise InitException("invalid port number: %s" % port) from None options = {} if len(parts) == 2: options = parse_simple_dict(parts[1]) ip_sockets[(host, iport)] = options return ip_sockets
def get_sound_source_options(plugin, options_str, device, want_monitor_device, remote): """ Given a plugin (short name), options string and remote info, return the options for the plugin given, using the dynamic defaults (which may use remote info) and applying the options string on top. """ #ie: get_sound_source_options("audiotestsrc", "wave=4,freq=220", {remote_pulseaudio_server=XYZ}): #use the defaults as starting point: defaults_fn = DEFAULT_SRC_PLUGIN_OPTIONS.get(plugin) log("DEFAULT_SRC_PLUGIN_OPTIONS(%s)=%s", plugin, defaults_fn) if defaults_fn: options = defaults_fn(device, want_monitor_device, remote) log("%s%s=%s", defaults_fn, (device, want_monitor_device, remote), options) if options is None: #means failure return None else: options = {} #if we add support for choosing devices in the GUI, #this code will then get used: if device and plugin in SRC_HAS_DEVICE_NAME: #assume the user knows the "device-name"... #(since I have no idea where to get the "device" string) options["device-name"] = device options.update(parse_simple_dict(options_str)) return options
def parse_auth_line(line): ldata = line.split(b"|") log("found %s fields", len(ldata)) assert len(ldata)>=4, "not enough fields" #parse fields: username = ldata[0] password = ldata[1] uid = getuid(ldata[2]) gid = getgid(ldata[3]) displays = ldata[4].split(b",") env_options = {} session_options = {} if len(ldata)>=6: env_options = parse_simple_dict(ldata[5], ";") if len(ldata)>=7: session_options = parse_simple_dict(ldata[6], ";") return username, password, uid, gid, displays, env_options, session_options
def parse_auth_line(line): ldata = line.split(b"|") log("found %s fields", len(ldata)) assert len(ldata) >= 4, "not enough fields" #parse fields: username = ldata[0] password = ldata[1] uid = getuid(ldata[2]) gid = getgid(ldata[3]) displays = ldata[4].split(b",") env_options = {} session_options = {} if len(ldata) >= 6: env_options = parse_simple_dict(ldata[5], ";") if len(ldata) >= 7: session_options = parse_simple_dict(ldata[6], ";") return username, password, uid, gid, displays, env_options, session_options
def parse_session_data(self, data): try: uid = parse_uid(data["uid"]) gid = parse_gid(data["gid"]) displays = [] env_options = {} session_options = {} if data["displays"]: displays = [x.strip() for x in str(data["displays"]).split(",")] if data["env_options"]: env_options = parse_simple_dict(str(data["env_options"]), ";") if data["session_options"]: session_options=parse_simple_dict(str(data["session_options"]), ";") except Exception as e: log("get_sessions() error on row %s", data, exc_info=True) log.error("Error: sqlauth database row parsing problem:") log.error(" %s", e) return None return uid, gid, displays, env_options, session_options
def parse_session_data(self, data): try: uid = data[0] gid = data[1] displays = [] env_options = {} session_options = {} if len(data)>2: displays = [x.strip() for x in str(data[2]).split(",")] if len(data)>3: env_options = parse_simple_dict(str(data[3]), ";") if len(data)>4: session_options = parse_simple_dict(str(data[4]), ";") except Exception as e: log("parse_session_data() error on row %s", data, exc_info=True) log.error("Error: sqlauth database row parsing problem:") log.error(" %s", e) return None return uid, gid, displays, env_options, session_options
def get_auth_module(self, socket_type, auth_str, opts): authlog("get_auth_module(%s, %s, {..})", socket_type, auth_str) if not auth_str: return None #separate options from the auth module name parts = auth_str.split(":", 1) auth = parts[0] auth_options = {} if len(parts) > 1: auth_options = parse_simple_dict(parts[1]) if auth == "sys": #resolve virtual "sys" auth: if sys.platform.startswith("win"): auth = "win32" else: auth = "pam" authlog("will try to use sys auth module '%s' for %s", auth, sys.platform) from xpra.server.auth import fail_auth, reject_auth, allow_auth, none_auth, file_auth, multifile_auth, password_auth, env_auth AUTH_MODULES = { "fail": fail_auth, "reject": reject_auth, "allow": allow_auth, "none": none_auth, "env": env_auth, "password": password_auth, "multifile": multifile_auth, "file": file_auth, } try: from xpra.server.auth import pam_auth AUTH_MODULES["pam"] = pam_auth except Exception as e: authlog("cannot load pam auth: %s", e) if sys.platform.startswith("win"): try: from xpra.server.auth import win32_auth AUTH_MODULES["win32"] = win32_auth except Exception as e: authlog.error( "Error: cannot load the MS Windows authentication module:") authlog.error(" %s", e) auth_module = AUTH_MODULES.get(auth) if not auth_module: raise InitException( "cannot find authentication module '%s' (supported: %s)" % (auth, csv(AUTH_MODULES.keys()))) try: auth_module.init(opts) auth_class = getattr(auth_module, "Authenticator") auth_class.auth_name = auth.lower() return auth, auth_class, auth_options except Exception as e: raise InitException("Authenticator class not found in %s" % auth_module)
def parse_bind_vsock(bind_vsock): vsock_sockets = {} if bind_vsock: from xpra.scripts.parsing import parse_vsock #pylint: disable=import-outside-toplevel for spec in bind_vsock: parts = spec.split(",", 1) cid, iport = parse_vsock(parts[0]) options = {} if len(parts) == 2: options = parse_simple_dict(parts[1]) vsock_sockets[(cid, iport)] = options return vsock_sockets
def parse_bind_vsock(bind_vsock): vsock_sockets = {} if bind_vsock: from xpra.scripts.main import parse_vsock for spec in bind_vsock: parts = spec.split(",", 1) cid, iport = parse_vsock(parts[0]) options = {} if len(parts) == 2: options = parse_simple_dict(parts[1]) vsock_sockets[(cid, iport)] = options return vsock_sockets
def makeRootWindowModels(self): screenlog("makeRootWindowModels() root=%s, display_options=%s", self.root, self.display_options) self.capture = self.setup_capture() model_class = self.get_root_window_model_class() models = [] display_name = prettify_plug_name(self.root.get_screen().get_display().get_name()) monitors = self.get_shadow_monitors() match_str = None multi_window = MULTI_WINDOW geometries = None if "=" in self.display_options: #parse the display options as a dictionary: opt_dict = parse_simple_dict(self.display_options) windows = opt_dict.get("windows") if windows: self.window_matches = windows.split("/") return self.makeDynamicWindowModels() match_str = opt_dict.get("plug") multi_window = parse_bool("multi-window", opt_dict.get("multi-window", multi_window)) geometries_str = opt_dict.get("geometry") if geometries_str: geometries = parse_geometries(geometries_str) else: try: geometries = parse_geometries(self.display_options) except Exception: match_str = self.display_options if not multi_window or geometries: for geometry in (geometries or (self.root.get_geometry()[:4],)): model = model_class(self.root, self.capture, display_name, geometry) models.append(model) return models found = [] screenlog("capture inputs matching %r", match_str or "all") for i, monitor in enumerate(monitors): plug_name, x, y, width, height, scale_factor = monitor title = display_name if plug_name or i>1: title = plug_name or str(i) found.append(plug_name or title) if match_str and not(title in match_str or plug_name in match_str): screenlog.info(" skipped monitor %s", plug_name or title) continue geometry = (x, y, width, height) model = model_class(self.root, self.capture, title, geometry) models.append(model) screenlog("monitor %i: %10s geometry=%s, scale factor=%s", i, title, geometry, scale_factor) screenlog("makeRootWindowModels()=%s", models) if not models and match_str: screenlog.warn("Warning: no monitors found matching %r", match_str) screenlog.warn(" only found: %s", csv(found)) return models
def parse_auth_line(line): ldata = line.split(b"|") assert len(ldata)>=2, "not enough fields: %i" % (len(ldata)) log("found %s fields", len(ldata)) #parse fields: username = ldata[0] password = ldata[1] if len(ldata)>=5: uid = parse_uid(bytestostr(ldata[2])) gid = parse_gid(bytestostr(ldata[3])) displays = bytestostr(ldata[4]).split(",") else: #this will use the default value, usually "nobody": uid = parse_uid(None) gid = parse_gid(None) displays = [] env_options = {} session_options = {} if len(ldata)>=6: env_options = parse_simple_dict(ldata[5], b";") if len(ldata)>=7: session_options = parse_simple_dict(ldata[6], b";") return username, password, uid, gid, displays, env_options, session_options
def get_auth_module(self, socket_type, auth_str, opts): authlog("get_auth_module(%s, %s, {..})", socket_type, auth_str) if not auth_str: return None #separate options from the auth module name parts = auth_str.split(":", 1) auth = parts[0] auth_options = {} if len(parts)>1: auth_options = parse_simple_dict(parts[1]) if auth=="sys": #resolve virtual "sys" auth: if sys.platform.startswith("win"): auth = "win32" else: auth = "pam" authlog("will try to use sys auth module '%s' for %s", auth, sys.platform) from xpra.server.auth import fail_auth, reject_auth, allow_auth, none_auth, file_auth, multifile_auth, password_auth, env_auth AUTH_MODULES = { "fail" : fail_auth, "reject" : reject_auth, "allow" : allow_auth, "none" : none_auth, "env" : env_auth, "password" : password_auth, "multifile" : multifile_auth, "file" : file_auth, } try: from xpra.server.auth import pam_auth AUTH_MODULES["pam"] = pam_auth except Exception as e: authlog("cannot load pam auth: %s", e) if sys.platform.startswith("win"): try: from xpra.server.auth import win32_auth AUTH_MODULES["win32"] = win32_auth except Exception as e: authlog.error("Error: cannot load the MS Windows authentication module:") authlog.error(" %s", e) auth_module = AUTH_MODULES.get(auth) if not auth_module: raise InitException("cannot find authentication module '%s' (supported: %s)" % (auth, csv(AUTH_MODULES.keys()))) try: auth_module.init(opts) auth_class = getattr(auth_module, "Authenticator") auth_class.auth_name = auth.lower() return auth, auth_class, auth_options except Exception as e: raise InitException("Authenticator class not found in %s" % auth_module)
def parse_auth_line(line): ldata = line.split(b"|") log("found %s fields", len(ldata)) assert len(ldata)>=4, "not enough fields" #parse fields: username = ldata[0] password = ldata[1] def getsysid(s, get_default_value): if s: try: return int(s) except: pass return get_default_value() uid = getsysid(ldata[2], os.getuid) gid = getsysid(ldata[3], os.getgid) displays = ldata[4].split(b",") env_options = {} session_options = {} if len(ldata)>=6: env_options = parse_simple_dict(ldata[5], ";") if len(ldata)>=7: session_options = parse_simple_dict(ldata[6], ";") return username, password, uid, gid, displays, env_options, session_options
def get_auth_module(auth_str, cwd=os.getcwd(), **auth_options): log("get_auth_module(%s, {..})", auth_str) #separate options from the auth module name #either with ":" or "," as separator scpos = auth_str.find(":") cpos = auth_str.find(",") if cpos < 0 or scpos < cpos: parts = auth_str.split(":", 1) else: parts = auth_str.split(",", 1) auth = parts[0] if len(parts) > 1: auth_options.update(parse_simple_dict(parts[1])) auth_options["exec_cwd"] = cwd try: if auth == "sys": #resolve virtual "sys" auth: if WIN32: auth_modname = "win32_auth" else: auth_modname = "pam_auth" log("will try to use sys auth module '%s' for %s", auth, sys.platform) else: auth_modname = auth.replace("-", "_") + "_auth" auth_mod_name = "xpra.server.auth." + auth_modname log("auth module name for '%s': '%s'", auth, auth_mod_name) auth_module = __import__(auth_mod_name, {}, {}, ["Authenticator"]) except ImportError as e: log("cannot load %s auth for %r", auth, auth_str, exc_info=True) raise InitException( "cannot load authentication module '%s' for %r: %s" % (auth, auth_str, e)) from None log("auth module for '%s': %s", auth, auth_module) try: auth_class = auth_module.Authenticator auth_class.auth_name = auth.lower() return auth, auth_module, auth_class, auth_options except Exception as e: log("cannot access authenticator class", exc_info=True) raise InitException("authentication setup error in %s: %s" % (auth_module, e)) from None
def get_challenge_handler(self, auth, import_error_logger): #the module may have attributes, #ie: file:filename=password.txt parts = auth.split(":", 1) mod_name = parts[0] kwargs = {} if len(parts)==2: kwargs = parse_simple_dict(parts[1]) auth_mod_name = "xpra.client.auth.%s_handler" % mod_name authlog("auth module name for '%s': '%s'", auth, auth_mod_name) try: auth_module = __import__(auth_mod_name, {}, {}, ["Handler"]) auth_class = auth_module.Handler instance = auth_class(self, **kwargs) return instance except ImportError as e: import_error_logger("Error: authentication handler %s not available", mod_name) import_error_logger(" %s", e) except Exception as e: authlog("get_challenge_handler(%s)", auth, exc_info=True) authlog.error("Error: cannot instantiate authentication handler") authlog.error(" '%s': %s", mod_name, e) return None
def run_sound(mode, error_cb, options, args): """ this function just parses command line arguments to feed into the sound subprocess class, which in turn just feeds them into the sound pipeline class (sink.py or src.py) """ from xpra.gtk_common.gobject_compat import want_gtk3 want_gtk3(True) gst = import_gst() if not gst: return 1 info = mode.replace("_sound_", "") #ie: "_sound_record" -> "record" from xpra.platform import program_context with program_context("Xpra-Audio-%s" % info, "Xpra Audio %s" % info): log("run_sound(%s, %s, %s, %s) gst=%s", mode, error_cb, options, args, gst) if mode=="_sound_record": subproc = sound_record elif mode=="_sound_play": subproc = sound_play elif mode=="_sound_query": plugins = get_all_plugin_names() sources = [x for x in get_source_plugins() if x in plugins] sinks = [x for x in get_sink_plugins() if x in plugins] from xpra.sound.gstreamer_util import gst_version, pygst_version import struct bits = struct.calcsize("P")*8 d = { "encoders" : can_encode(), "decoders" : can_decode(), "sources" : sources, "source.default" : get_default_source() or "", "sinks" : sinks, "sink.default" : get_default_sink() or "", "muxers" : get_muxers(), "demuxers" : get_demuxers(), "gst.version" : [int(x) for x in gst_version], "pygst.version" : pygst_version, "plugins" : plugins, "python.version" : sys.version_info[:3], "python.bits" : bits, } if BUNDLE_METADATA: d["bundle-metadata"] = True for k,v in d.items(): if type(v) in (list, tuple): v = ",".join(str(x) for x in v) print("%s=%s" % (k, v)) return 0 else: log.error("unknown mode: %s" % mode) return 1 assert len(args)>=6, "not enough arguments" #the plugin to use (ie: 'pulsesrc' for src.py or 'autoaudiosink' for sink.py) plugin = args[2] #plugin options (ie: "device=monitor_device,something=value") options = parse_simple_dict(args[3]) #codecs: codecs = [x.strip() for x in args[4].split(",")] #codec options: codec_options = parse_simple_dict(args[5]) #volume (optional): try: volume = int(args[6]) except: volume = 1.0 ss = None try: ss = subproc(plugin, options, codecs, codec_options, volume) ss.start() return 0 except InitExit as e: log.error("%s: %s", info, e) return e.status except InitException as e: log.error("%s: %s", info, e) return 1 except Exception: log.error("run_sound%s error", (mode, error_cb, options, args), exc_info=True) return 1 finally: if ss: ss.stop()
def run_sound(mode, error_cb, options, args): """ this function just parses command line arguments to feed into the sound subprocess class, which in turn just feeds them into the sound pipeline class (sink.py or src.py) """ #we have to import gstreamer before init() on OSX, #because init will end up import gobject, #which means choosing between gi and gtk2 bindings from xpra.sound.gstreamer_util import import_gst, get_pygst_version gst = import_gst() from xpra.gtk_common.gobject_compat import want_gtk3 want_gtk3(get_pygst_version()[0]>0) from xpra.platform import program_context with program_context("Xpra"): log("run_sound(%s, %s, %s, %s) gst=%s", mode, error_cb, options, args, gst) if not gst: return 1 if mode=="_sound_record": subproc = sound_record info = "record" elif mode=="_sound_play": subproc = sound_play info = "play" elif mode=="_sound_query": plugins = get_all_plugin_names() sources = [x for x in get_source_plugins() if x in plugins] from xpra.sound.gstreamer_util import gst_version, pygst_version d = {"encoders" : can_encode(), "decoders" : can_decode(), "sources" : sources, "muxers" : get_muxers(), "demuxers" : get_demuxers(), "gst.version" : gst_version, "pygst.version" : pygst_version, "plugins" : plugins, "python.version" : sys.version_info[:3], } for k,v in d.items(): print("%s=%s" % (k, ",".join(str(x) for x in v))) return 0 else: log.error("unknown mode: %s" % mode) return 1 assert len(args)>=6, "not enough arguments" #the plugin to use (ie: 'pulsesrc' for src.py or 'autoaudiosink' for sink.py) plugin = args[2] #plugin options (ie: "device=monitor_device,something=value") options = parse_simple_dict(args[3]) #codecs: codecs = [x.strip() for x in args[4].split(",")] #codec options: codec_options = parse_simple_dict(args[5]) #volume (optional): try: volume = int(args[6]) except: volume = 1.0 ss = None try: ss = subproc(plugin, options, codecs, codec_options, volume) ss.start() return 0 except InitExit as e: log.error("%s: %s", info, e) return e.status except InitException as e: log.error("%s: %s", info, e) return 1 except Exception: log.error("run_sound%s error", (mode, error_cb, options, args), exc_info=True) return 1 finally: if ss: ss.stop()
PRINTER_PREFIX, ADD_LOCAL_PRINTERS) log("pycups settings: FORWARDER_TMPDIR=%s", FORWARDER_TMPDIR) log("pycups settings: SKIPPED_PRINTERS=%s", SKIPPED_PRINTERS) MIMETYPE_TO_PRINTER = { "application/postscript" : "Generic PostScript Printer", "application/pdf" : "Generic PDF Printer", } MIMETYPE_TO_PPD = { "application/postscript" : "CUPS-PDF.ppd", "application/pdf" : "Generic-PDF_Printer-PDF.ppd", } dco = os.environ.get("XPRA_DEFAULT_CUPS_OPTIONS", "fit-to-page=True") DEFAULT_CUPS_OPTIONS = parse_simple_dict(dco) log("DEFAULT_CUPS_OPTIONS=%s", DEFAULT_CUPS_OPTIONS) #allows us to inject the lpadmin and lpinfo commands from the config file def set_lpadmin_command(lpadmin): global LPADMIN LPADMIN = lpadmin def set_add_printer_options(options): global ADD_OPTIONS ADD_OPTIONS = options def set_lpinfo_command(lpinfo): global LPINFO LPINFO = lpinfo
def setup_local_sockets(bind, socket_dir, socket_dirs, display_name, clobber, mmap_group="auto", socket_permissions="600", username="", uid=0, gid=0): log = get_network_logger() log("setup_local_sockets%s", (bind, socket_dir, socket_dirs, display_name, clobber, mmap_group, socket_permissions, username, uid, gid)) if not bind: return {} if not socket_dir and (not socket_dirs or (len(socket_dirs) == 1 and not socket_dirs[0])): if WIN32: socket_dirs = [""] else: raise InitExit( EXIT_SOCKET_CREATION_ERROR, "at least one socket directory must be set to use unix domain sockets" ) from xpra.platform.dotxpra import DotXpra, norm_makepath dotxpra = DotXpra(socket_dir or socket_dirs[0], socket_dirs, username, uid, gid) if display_name is not None and not WIN32: display_name = normalize_local_display_name(display_name) defs = {} try: sockpaths = {} log("setup_local_sockets: bind=%s, dotxpra=%s", bind, dotxpra) for b in bind: if b in ("none", ""): continue parts = b.split(",") sockpath = parts[0] options = {} if len(parts) == 2: options = parse_simple_dict(parts[1]) if sockpath == "auto": assert display_name is not None for sockpath in dotxpra.norm_socket_paths(display_name): sockpaths[sockpath] = options log("sockpaths(%s)=%s (uid=%i, gid=%i)", display_name, sockpaths, uid, gid) else: sockpath = dotxpra.osexpand(sockpath) if os.path.isabs(sockpath): pass elif sockpath.endswith("/") or (os.path.exists(sockpath) and os.path.isdir(sockpath)): assert display_name is not None sockpath = os.path.abspath(sockpath) if not os.path.exists(sockpath): os.makedirs(sockpath) sockpath = norm_makepath(sockpath, display_name) else: sockpath = dotxpra.socket_path(sockpath) sockpaths[sockpath] = options assert sockpaths, "no socket paths to try for %s" % b #expand and remove duplicate paths: tmp = {} for tsp, options in sockpaths.items(): sockpath = dotxpra.osexpand(tsp) if sockpath in tmp: log.warn("Warning: skipping duplicate bind path %s", sockpath) continue tmp[sockpath] = options sockpaths = tmp log("sockpaths=%s", sockpaths) #create listeners: if WIN32: from xpra.platform.win32.namedpipes.listener import NamedPipeListener from xpra.platform.win32.dotxpra import PIPE_PATH for sockpath, options in sockpaths.items(): npl = NamedPipeListener(sockpath) ppath = sockpath if ppath.startswith(PIPE_PATH): ppath = ppath[len(PIPE_PATH):] log.info("created named pipe '%s'", ppath) defs[("named-pipe", npl, sockpath, npl.stop)] = options else: def checkstate(sockpath, state): if state not in (DotXpra.DEAD, DotXpra.UNKNOWN): if state == DotXpra.INACCESSIBLE: raise InitException( "An xpra server is already running at %s\n" % (sockpath, )) raise InitExit( EXIT_SERVER_ALREADY_EXISTS, "You already have an xpra server running at %s\n" " (did you want 'xpra upgrade'?)" % (sockpath, )) #remove exisiting sockets if clobber is set, #otherwise verify there isn't a server already running #and create the directories for the sockets: unknown = [] for sockpath in sockpaths: if clobber and os.path.exists(sockpath): os.unlink(sockpath) else: state = dotxpra.get_server_state(sockpath, 1) log("state(%s)=%s", sockpath, state) checkstate(sockpath, state) if state == dotxpra.UNKNOWN: unknown.append(sockpath) d = os.path.dirname(sockpath) try: kwargs = {} if d in ("/var/run/xpra", "/run/xpra"): #this is normally done by tmpfiles.d, #but we may need to do it ourselves in some cases: kwargs["mode"] = SOCKET_DIR_MODE xpra_gid = get_group_id(SOCKET_DIR_GROUP) if xpra_gid > 0: kwargs["gid"] = xpra_gid log("creating sockdir=%s, kwargs=%s" % (d, kwargs)) dotxpra.mksockdir(d, **kwargs) log("%s permission mask: %s", d, oct(os.stat(d).st_mode)) except Exception as e: log.warn("Warning: failed to create socket directory '%s'", d) log.warn(" %s", e) del e #wait for all the unknown ones: log("sockets in unknown state: %s", unknown) if unknown: #re-probe them using threads so we can do them in parallel: threads = [] def timeout_probe(sockpath): #we need a loop because "DEAD" sockets may return immediately #(ie: when the server is starting up) start = monotonic_time() while monotonic_time() - start < WAIT_PROBE_TIMEOUT: state = dotxpra.get_server_state( sockpath, WAIT_PROBE_TIMEOUT) log("timeout_probe() get_server_state(%s)=%s", sockpath, state) if state not in (DotXpra.UNKNOWN, DotXpra.DEAD): break sleep(1) log.warn( "Warning: some of the sockets are in an unknown state:") for sockpath in unknown: log.warn(" %s", sockpath) t = start_thread(timeout_probe, "probe-%s" % sockpath, daemon=True, args=(sockpath, )) threads.append(t) log.warn( " please wait as we allow the socket probing to timeout") #wait for all the threads to do their job: for t in threads: t.join(WAIT_PROBE_TIMEOUT + 1) if sockpaths: #now we can re-check quickly: #(they should all be DEAD or UNKNOWN): for sockpath in sockpaths: state = dotxpra.get_server_state(sockpath, 1) log("state(%s)=%s", sockpath, state) checkstate(sockpath, state) try: if os.path.exists(sockpath): os.unlink(sockpath) except OSError: pass #socket permissions: if mmap_group.lower() in TRUE_OPTIONS: #when using the mmap group option, use '660' sperms = 0o660 else: #parse octal mode given as config option: try: if isinstance(socket_permissions, int): sperms = socket_permissions else: #assume octal string: sperms = int(socket_permissions, 8) assert 0 <= sperms <= 0o777, "invalid socket permission value %s" % oct( sperms) except ValueError: raise ValueError("invalid socket permissions " + "(must be an octal number): '%s'" % socket_permissions) from None #now try to create all the sockets: for sockpath, options in sockpaths.items(): #create it: try: sock, cleanup_socket = create_unix_domain_socket( sockpath, sperms) log.info("created unix domain socket '%s'", sockpath) defs[("unix-domain", sock, sockpath, cleanup_socket)] = options except Exception as e: handle_socket_error(sockpath, sperms, e) del e except Exception: for sock, cleanup_socket in defs.items(): try: cleanup_socket() except Exception as e: log.error("Error cleaning up socket %s:", sock) log.error(" %s", e) del e raise return defs
def makeRootWindowModels(self): screenlog("makeRootWindowModels() root=%s, display_options=%s", self.root, self.display_options) self.capture = self.setup_capture() model_class = self.get_root_window_model_class() models = [] display_name = prettify_plug_name( self.root.get_screen().get_display().get_name()) monitors = self.get_shadow_monitors() match_str = None multi_window = MULTI_WINDOW geometries = None def parse_geometry(s): try: parts = s.split("@") if len(parts) == 1: x = y = 0 else: x, y = [int(v.strip(" ")) for v in parts[1].split("x")] w, h = [int(v.strip(" ")) for v in parts[0].split("x")] geometry = [x, y, w, h] screenlog("capture geometry: %s", geometry) return geometry except ValueError: screenlog("failed to parse geometry %r", s, exc_info=True) screenlog.error( "Error: invalid display geometry specified: %r", s) screenlog.error(" use the format: WIDTHxHEIGHT@x,y") raise def parse_geometries(s): g = [] for geometry_str in s.split("/"): if geometry_str: g.append(parse_geometry(geometry_str)) return g if "=" in self.display_options: #parse the display options as a dictionary: opt_dict = parse_simple_dict(self.display_options) match_str = opt_dict.get("plug") multi_window = parse_bool( "multi-window", opt_dict.get("multi-window", multi_window)) geometries_str = opt_dict.get("geometry") if geometries_str: geometries = parse_geometries(geometries_str) else: try: geometries = parse_geometries(self.display_options) except: match_str = self.display_options if not multi_window or geometries: for geometry in (geometries or (None, )): model = model_class(self.root, self.capture) model.title = display_name if geometry: model.geometry = geometry models.append(model) return models found = [] screenlog("capture inputs matching %r", match_str or "all") for i, monitor in enumerate(monitors): plug_name, x, y, width, height, scale_factor = monitor title = display_name if plug_name or i > 1: title = plug_name or str(i) found.append(plug_name or title) if match_str and not (title in match_str or plug_name in match_str): screenlog.info(" skipped monitor %s", plug_name or title) continue model = model_class(self.root, self.capture) model.title = title model.geometry = (x, y, width, height) models.append(model) screenlog("monitor %i: %10s geometry=%s, scale factor=%s", i, title, model.geometry, scale_factor) screenlog("makeRootWindowModels()=%s", models) if not models and match_str: screenlog.warn("Warning: no monitors found matching %r", match_str) screenlog.warn(" only found: %s", csv(found)) return models