Example #1
0
def get_lpinfo_drv(make_and_model):
    if not LPINFO:
        log.error("Error: lpinfo command is not defined")
        return None
    command = shlex.split(LPINFO) + ["--make-and-model", make_and_model, "-m"]
    log("get_lpinfo_drv(%s) command=%s", make_and_model, command)
    try:
        proc = Popen(command, stdout=PIPE, stderr=PIPE, start_new_session=True)
    except Exception as e:
        log("get_lp_info_drv(%s) lpinfo command %s failed",
            make_and_model,
            command,
            exc_info=True)
        log.error("Error: lpinfo command failed to run")
        log.error(" %s", e)
        log.error(" command used: '%s'", " ".join(command))
        return None
    #use the global child reaper to make sure this doesn't end up as a zombie
    from xpra.child_reaper import getChildReaper
    cr = getChildReaper()
    cr.add_process(proc, "lpinfo", command, ignore=True, forget=True)
    from xpra.make_thread import start_thread

    def watch_lpinfo():
        #give it 15 seconds to run:
        for _ in range(15):
            if proc.poll() is not None:
                return  #finished already
            time.sleep(1)
        if proc.poll() is not None:
            return
        log.warn("Warning: lpinfo command is taking too long,")
        log.warn(" is the cups server running?")
        try:
            proc.terminate()
        except Exception as e:
            log("%s.terminate()", proc, exc_info=True)
            log.error("Error: failed to terminate lpinfo command")
            log.error(" %s", e)

    start_thread(watch_lpinfo, "lpinfo watcher", daemon=True)
    out, err = proc.communicate()
    if proc.wait() != 0:
        log.warn("Warning: lpinfo command failed and returned %s",
                 proc.returncode)
        log.warn(" command used: '%s'", " ".join(command))
        return None
    try:
        out = out.decode()
    except Exception:
        out = str(out)
    log("lpinfo out=%r", out)
    log("lpinfo err=%r", err)
    if err:
        log.warn("Warning: lpinfo command produced some warnings:")
        log.warn(" %r", err)
    for line in out.splitlines():
        if line.startswith("drv://"):
            return line.split(" ")[0]
    return None
Example #2
0
    def late_start(self):
        def do_late_start():
            #wait for all threaded init to complete
            self.wait_for_threaded_init()
            self.exec_start_late_commands()

        start_thread(do_late_start, "command-late-start", daemon=True)
Example #3
0
 def do_run(self, attach=False):
     self.hide()
     cmd = self.get_run_command(attach)
     log("do_run(%s) cmd=%s", attach, cmd)
     proc = exec_command(cmd)
     if proc:
         start_thread(self.wait_for_subprocess, "wait-%i" % proc.pid, daemon=True, args=(proc,))
    def run(self):
        log("ProxyProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), getuid(), getgid())
        setuidgid(self.uid, self.gid)
        if self.env_options:
            #TODO: whitelist env update?
            os.environ.update(self.env_options)
        self.video_init()

        log.info("new proxy instance started")
        log.info(" for client %s", self.client_conn)
        log.info(" and server %s", self.server_conn)

        signal.signal(signal.SIGTERM, self.signal_quit)
        signal.signal(signal.SIGINT, self.signal_quit)
        log("registered signal handler %s", self.signal_quit)

        start_thread(self.server_message_queue, "server message queue")

        if not self.create_control_socket():
            #TODO: should send a message to the client
            return
        self.control_socket_thread = start_thread(self.control_socket_loop, "control")

        self.main_queue = Queue()
        #setup protocol wrappers:
        self.server_packets = Queue(PROXY_QUEUE_SIZE)
        self.client_packets = Queue(PROXY_QUEUE_SIZE)
        self.client_protocol = Protocol(self, self.client_conn, self.process_client_packet, self.get_client_packet)
        self.client_protocol.restore_state(self.client_state)
        self.server_protocol = Protocol(self, self.server_conn, self.process_server_packet, self.get_server_packet)
        #server connection tweaks:
        self.server_protocol.large_packets.append("draw")
        self.server_protocol.large_packets.append("window-icon")
        self.server_protocol.large_packets.append("keymap-changed")
        self.server_protocol.large_packets.append("server-settings")
        if self.caps.boolget("file-transfer"):
            self.client_protocol.large_packets.append("send-file")
            self.client_protocol.large_packets.append("send-file-chunk")
            self.server_protocol.large_packets.append("send-file")
            self.server_protocol.large_packets.append("send-file-chunk")
        self.server_protocol.set_compression_level(self.session_options.get("compression_level", 0))
        self.server_protocol.enable_default_encoder()

        self.lost_windows = set()
        self.encode_queue = Queue()
        self.encode_thread = start_thread(self.encode_loop, "encode")

        log("starting network threads")
        self.server_protocol.start()
        self.client_protocol.start()

        self.send_hello()
        self.timeout_add(VIDEO_TIMEOUT*1000, self.timeout_video_encoders)

        try:
            self.run_queue()
        except KeyboardInterrupt as e:
            self.stop(str(e))
        finally:
            log("ProxyProcess.run() ending %s", os.getpid())
Example #5
0
 def cleanup():
     for source in tuple(sources):
         GLib.source_remove(source)
         sources.remove(source)
     for c in upnp_cleanup:
         if c:
             start_thread(c, "pnp-cleanup-%s" % c, daemon=True)
Example #6
0
 def check(self):
     if self.progress:
         return
     self.newer_version = None
     glib.timeout_add(1000, self.update_label)
     from xpra.make_thread import start_thread
     start_thread(self.do_check, "version check", daemon=True)
Example #7
0
 def close(self):
     log("%s.close() close callback=%s, readable=%s, writeable=%s",
         self, self._close_cb, self._readable, self._writeable)
     super().close()
     cc = self._close_cb
     if cc:
         self._close_cb = None
         log("%s.close() calling %s", self, cc)
         try:
             cc()
         except Exception:
             log.error("%s.close() error on callback %s", self, cc, exc_info=True)
     def close_files_thread():
         log("close_files_thread() _readable=%s", self._readable)
         log("close_files_thread() calling %s", self._readable.close)
         try:
             self._readable.close()
         except IOError as e:
             log("close_files_thread() %s", self._readable, e)
         log("close_files_thread() _writeable=%s", self._writeable)
         log("close_files_thread() calling %s", self._writeable.close)
         try:
             self._writeable.close()
         except IOError as e:
             log("close_files_thread() %s", self._writeable, e)
     start_thread(close_files_thread, "close-files-thread", daemon=True)
     log("%s.close() done", self)
Example #8
0
 def check_for_end(*_args):
     qtime = ss.queue.get_property("current-level-time") // MS_TO_NS
     if qtime <= 0:
         log.info("underrun (end of stream)")
         start_thread(ss.stop, "stop", daemon=True)
         GLib.timeout_add(500, glib_mainloop.quit)
         return False
     return True
Example #9
0
 def send_initial_data(self, ss, caps, send_ui, share_count):
     if not getattr(ss, "xdg_menu", False):
         return
     if ss.xdg_menu_update:
         #this method may block if the menus are still being loaded,
         #so do it in a throw-away thread:
         start_thread(self.send_xdg_menu_data, "send-xdg-menu-data", True,
                      (ss, ))
Example #10
0
    def load_menu_data(self, force_reload=False):
        #start loading in a thread,
        #as this may take a while and
        #so server startup can complete:
        def load():
            self.get_menu_data(force_reload)
            self.get_desktop_sessions()

        start_thread(load, "load-menu-data", True)
Example #11
0
 def do_run(self, attach=False):
     self.hide()
     cmd = self.get_run_command(attach)
     proc = exec_command(cmd)
     if proc:
         from xpra.make_thread import start_thread
         start_thread(self.wait_for_subprocess,
                      "wait-%i" % proc.pid,
                      daemon=True,
                      args=(proc, ))
Example #12
0
 def __init__(self, *args):
     super().__init__(*args)
     self.log_file = None
     if CURSES_LOG:
         self.log_file = open(CURSES_LOG, "ab")
     self.paused = False
     self.stdscr = None
     self.modified = False
     self.psprocess = {}
     start_thread(self.input_thread, "input-thread", daemon=True)
Example #13
0
 def run(self):
     from xpra.make_thread import start_thread
     start_thread(self.read_stdin, "read-stdin", True)
     self.show_all()
     force_focus()
     self.present()
     self.timeout_timer = GLib.timeout_add(TIMEOUT*1000, self.timeout)
     self.pulse_timer = GLib.timeout_add(100, self.pulse)
     Gtk.main()
     return self.exit_code or 0
Example #14
0
 def show_html5(*_args):
     from xpra.scripts.main import run_html5
     from xpra.make_thread import start_thread
     url_options = {}
     try:
         for k in ("port", "host", "username", "mode", "display"):
             v = self.client.display_desc.get(k)
             if v is not None:
                 url_options[k] = v
     except Exception:
         pass
     start_thread(run_html5, "open HTML5 client", True, args=(url_options, ))
Example #15
0
    def run(self):
        register_SIGUSR_signals(self.idle_add)
        client_protocol_class = get_client_protocol_class(self.client_conn.socktype)
        server_protocol_class = get_server_protocol_class(self.server_conn.socktype)
        self.client_protocol = client_protocol_class(self, self.client_conn,
                                                     self.process_client_packet, self.get_client_packet)
        self.client_protocol.restore_state(self.client_state)
        self.server_protocol = server_protocol_class(self, self.server_conn,
                                                     self.process_server_packet, self.get_server_packet)
        self.log_start()

        log("ProxyProcessProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), getuid(), getgid())
        set_proc_title("Xpra Proxy Instance for %s" % self.server_conn)
        if POSIX and (getuid()!=self.uid or getgid()!=self.gid):
            #do we need a valid XDG_RUNTIME_DIR for the socket-dir?
            username = get_username_for_uid(self.uid)
            socket_dir = osexpand(self.socket_dir, username, self.uid, self.gid)
            if not os.path.exists(socket_dir):
                log("the socket directory '%s' does not exist, checking for $XDG_RUNTIME_DIR path", socket_dir)
                for prefix in ("/run/user/", "/var/run/user/"):
                    if socket_dir.startswith(prefix):
                        from xpra.scripts.server import create_runtime_dir
                        xrd = os.path.join(prefix, str(self.uid))   #ie: /run/user/99
                        log("creating XDG_RUNTIME_DIR=%s for uid=%i, gid=%i", xrd, self.uid, self.gid)
                        create_runtime_dir(xrd, self.uid, self.gid)
                        break
            #change uid or gid:
            setuidgid(self.uid, self.gid)
        if self.env_options:
            #TODO: whitelist env update?
            os.environ.update(self.env_options)

        signal.signal(signal.SIGTERM, self.signal_quit)
        signal.signal(signal.SIGINT, self.signal_quit)
        log("registered signal handler %s", self.signal_quit)

        start_thread(self.server_message_queue, "server message queue")

        if not self.create_control_socket():
            return
        self.control_socket_thread = start_thread(self.control_socket_loop, "control", daemon=True)

        self.main_queue = Queue()

        ProxyInstance.run(self)

        try:
            QueueScheduler.run(self)
        except KeyboardInterrupt as e:
            self.stop(None, str(e))
        finally:
            log("ProxyProcess.run() ending %s", os.getpid())
Example #16
0
def exec_dialog_subprocess(cmd):
    try:
        log("exec_dialog_subprocess(%s)", cmd)
        kwargs = {}
        if POSIX:
            kwargs["close_fds"] = True
        else:
            #win32 platform code would create a log file for the command's output,
            #tell it not to do that:
            env = os.environ.copy()
            env["XPRA_LOG_TO_FILE"] = "0"
            kwargs["env"] = env
        proc = Popen(cmd, stdout=PIPE, stderr=PIPE, **kwargs)
        stdout = []
        stderr = []
        from xpra.gtk_common.gobject_compat import import_gtk
        gtk = import_gtk()

        def read_thread(fd, out):
            while proc.poll() is None:
                try:
                    v = fd.read()
                    if v:
                        out.append(v)
                except:
                    time.sleep(0.1)
            try:
                gtk.main_quit()
            except:
                pass

        from xpra.make_thread import start_thread
        start_thread(read_thread, "dialog-stdout-reader", True,
                     (proc.stdout, stdout))
        start_thread(read_thread, "dialog-stderr-reader", True,
                     (proc.stderr, stderr))
        if is_WSL():
            #WSL needs to wait before calling communicate,
            #is this still needed now that we read using threads?
            proc.wait()
        gtk.main()
        log("exec_dialog_subprocess(%s) returncode=%s", cmd, proc.poll())
        if stderr:
            log.warn("Warning: dialog process error output:")
            for x in (b"".join(stderr)).decode().splitlines():
                log.warn(" %s", x)
        return proc.returncode, (b"".join(stdout)).decode()
    except Exception as e:
        log("exec_dialog_subprocess(..)", exc_info=True)
        log.error("Error: failed to execute the dialog subcommand")
        log.error(" %s", e)
        return -1, None
Example #17
0
    def __init__(self, client, _opts):
        self.client = client
        self._kh_warning = False
        self._console_handler_added = False
        self._screensaver_state = False
        self._screensaver_timer = 0
        self._exit = False
        if SCREENSAVER_LISTENER_POLL_DELAY > 0:

            def log_screensaver():
                v = bool(
                    GetIntSystemParametersInfo(
                        win32con.SPI_GETSCREENSAVERRUNNING))
                log("SPI_GETSCREENSAVERRUNNING=%s", v)
                if self._screensaver_state != v:
                    self._screensaver_state = v
                    if v:
                        self.client.suspend()
                    else:
                        self.client.resume()
                return True

            self._screensaver_timer = client.timeout_add(
                SCREENSAVER_LISTENER_POLL_DELAY * 1000, log_screensaver)
        if CONSOLE_EVENT_LISTENER:
            self._console_handler_added = setup_console_event_listener(
                self.handle_console_event, True)
        from xpra.platform.win32.win32_events import get_win32_event_listener
        try:
            el = get_win32_event_listener(True)
            self._el = el
            if el:
                el.add_event_callback(win32con.WM_ACTIVATEAPP,
                                      self.activateapp)
                el.add_event_callback(win32con.WM_POWERBROADCAST,
                                      self.power_broadcast_event)
                el.add_event_callback(win32con.WM_MOVE, self.wm_move)
                el.add_event_callback(WM_WTSSESSION_CHANGE,
                                      self.session_change_event)
                el.add_event_callback(win32con.WM_INPUTLANGCHANGE,
                                      self.inputlangchange)
                el.add_event_callback(win32con.WM_WININICHANGE, self.inichange)
                el.add_event_callback(win32con.WM_ENDSESSION, self.end_session)
        except Exception as e:
            log.error("Error: cannot register focus and power callbacks:")
            log.error(" %s", e)
        self.keyboard_hook_id = None
        if FORWARD_WINDOWS_KEY and mixin_features.windows:
            from xpra.make_thread import start_thread
            start_thread(self.init_keyboard_listener,
                         "keyboard-listener",
                         daemon=True)
Example #18
0
 def __init__(self, *args):
     super().__init__(*args)
     self.log_file = None
     if CURSES_LOG:
         self.log_file = open(CURSES_LOG, "ab")
     self.info_request_pending = False
     self.server_last_info = typedict()
     self.server_last_info_time = 0
     self.info_timer = 0
     self.paused = False
     self.stdscr = None
     self.psprocess = {}
     self.setup()
     start_thread(self.input_thread, "input-thread", daemon=True)
Example #19
0
def get_lpinfo_drv(make_and_model):
    command = shlex.split(LPINFO)+["--make-and-model", make_and_model, "-m"]
    def preexec():
        os.setsid()
    log("get_lpinfo_drv(%s) command=%s", make_and_model, command)
    try:
        proc = subprocess.Popen(command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, close_fds=True, preexec_fn=preexec)
    except Exception as e:
        log("get_lp_info_drv(%s) lpinfo command %s failed", make_and_model, command, exc_info=True)
        log.error("Error: lpinfo command failed to run")
        log.error(" %s", e)
        log.error(" command used: '%s'", " ".join(command))
        return None
    #use the global child reaper to make sure this doesn't end up as a zombie
    from xpra.child_reaper import getChildReaper
    from xpra.util import nonl
    cr = getChildReaper()
    cr.add_process(proc, "lpinfo", command, ignore=True, forget=True)
    from xpra.make_thread import start_thread
    def watch_lpinfo():
        #give it 15 seconds to run:
        for _ in range(15):
            if proc.poll() is not None:
                return      #finished already
            time.sleep(1)
        log.warn("Warning: lpinfo command is taking too long,")
        log.warn(" is the cups server running?")
        proc.terminate()
    start_thread(watch_lpinfo, "lpinfo watcher", daemon=True)
    out, err = proc.communicate()
    if proc.wait()!=0:
        log.warn("Warning: lpinfo command failed and returned %s", proc.returncode)
        log.warn(" command used: '%s'", " ".join(command))
        return None
    if sys.version_info[0]>=3:
        try:
            out = out.decode()
        except:
            out = str(out)
    log("lpinfo out=%s", nonl(out))
    log("lpinfo err=%s", nonl(err))
    if err:
        log.warn("Warning: lpinfo command produced some warnings:")
        log.warn(" '%s'", nonl(err))
    for line in out.splitlines():
        if line.startswith("drv://"):
            return line.split(" ")[0]
    return None
Example #20
0
    def test_all(self):
        set_default_name("platform info test", "platform-info-test")
        init()
        t = start_thread(threaded_server_init, "server-init")
        t.join()
        with program_context() as p:
            assert repr(p)
            assert get_application_name() == "platform-info-test"
            assert get_prgname() == "platform info test"

        if WIN32:  # pragma: no cover
            #we can check for command_error and command_info
            #on win32 because those trigger dialogs
            return
        calls = []

        def ccall(*args):
            calls.append(args)

        xpra_main.error = ccall
        xpra_main.info = ccall
        command_error("error")
        command_info("info")
        assert len(calls) == 2, "expected 2 messages but got: %s" % (calls, )
        set_prgname(None)
        clean()
Example #21
0
    def run(self):
        log.info("started %s", self)
        log.info(" for client %s", self.client_protocol._conn)
        log.info(" and server %s", self.server_protocol._conn)
        self.video_init()

        #setup protocol wrappers:
        self.server_packets = Queue(PROXY_QUEUE_SIZE)
        self.client_packets = Queue(PROXY_QUEUE_SIZE)
        #server connection tweaks:
        for x in (b"input-devices", b"draw", b"window-icon", b"keymap-changed",
                  b"server-settings"):
            self.server_protocol.large_packets.append(x)
        if self.caps.boolget("file-transfer"):
            for x in (b"send-file", b"send-file-chunk"):
                self.server_protocol.large_packets.append(x)
                self.client_protocol.large_packets.append(x)
        self.server_protocol.set_compression_level(
            self.session_options.get("compression_level", 0))
        self.server_protocol.enable_default_encoder()

        self.lost_windows = set()
        self.encode_queue = Queue()
        self.encode_thread = start_thread(self.encode_loop, "encode")

        self.start_network_threads()
        if self.caps.boolget("ping-echo-sourceid"):
            self.schedule_client_ping()

        self.send_hello()
Example #22
0
    def __init__(self, core_encodings, encodings, default_encoding,
                 scaling_control, default_quality, default_min_quality,
                 default_speed, default_min_speed):
        log("ServerSource%s",
            (core_encodings, encodings, default_encoding, scaling_control,
             default_quality, default_min_quality, default_speed,
             default_min_speed))
        self.server_core_encodings = core_encodings
        self.server_encodings = encodings
        self.default_encoding = default_encoding
        self.scaling_control = scaling_control

        self.default_quality = default_quality  #default encoding quality for lossy encodings
        self.default_min_quality = default_min_quality  #default minimum encoding quality
        self.default_speed = default_speed  #encoding speed (only used by x264)
        self.default_min_speed = default_min_speed  #default minimum encoding speed

        self.default_batch_config = DamageBatchConfig(
        )  #contains default values, some of which may be supplied by the client
        self.global_batch_config = self.default_batch_config.clone(
        )  #global batch config

        self.vrefresh = -1
        self.supports_transparency = False
        self.encoding = None  #the default encoding for all windows
        self.encodings = ()  #all the encodings supported by the client
        self.core_encodings = ()
        self.window_icon_encodings = ["premult_argb32"]
        self.rgb_formats = ("RGB", )
        self.encoding_options = typedict()
        self.icons_encoding_options = typedict()
        self.default_encoding_options = typedict()
        self.auto_refresh_delay = 0

        self.zlib = True
        self.lz4 = use_lz4
        self.lzo = use_lzo

        #for managing the recalculate_delays work:
        self.calculate_window_pixels = {}
        self.calculate_window_ids = set()
        self.calculate_timer = 0
        self.calculate_last_time = 0

        #if we "proxy video", we will modify the video helper to add
        #new encoders, so we must make a deep copy to preserve the original
        #which may be used by other clients (other ServerSource instances)
        self.video_helper = getVideoHelper().clone()

        # the queues of damage requests we work through:
        self.encode_work_queue = Queue(
        )  #holds functions to call to compress data (pixels, clipboard)
        #items placed in this queue are picked off by the "encode" thread,
        #the functions should add the packets they generate to the 'packet_queue'
        self.packet_queue = deque(
        )  #holds actual packets ready for sending (already encoded)
        #these packets are picked off by the "protocol" via 'next_packet()'
        #format: packet, wid, pixels, start_send_cb, end_send_cb
        #(only packet is required - the rest can be 0/None for clipboard packets)
        self.encode_thread = start_thread(self.encode_loop, "encode")
Example #23
0
 def _process_send_file_chunk(self, packet):
     chunk_id, chunk, file_data, has_more = packet[1:5]
     filelog("_process_send_file_chunk%s", (chunk_id, chunk, "%i bytes" % len(file_data), has_more))
     chunk_state = self.receive_chunks_in_progress.get(chunk_id)
     if not chunk_state:
         filelog.error("Error: cannot find the file transfer id '%s'", nonl(bytestostr(chunk_id)))
         self.send("ack-file-chunk", chunk_id, False, "file transfer id not found", chunk)
         return
     fd = chunk_state[1]
     if chunk_state[-1]+1!=chunk:
         filelog.error("Error: chunk number mismatch, expected %i but got %i", chunk_state[-1]+1, chunk)
         self.send("ack-file-chunk", chunk_id, False, "chunk number mismatch", chunk)
         del self.receive_chunks_in_progress[chunk_id]
         os.close(fd)
         return
     #update chunk number:
     chunk_state[-1] = chunk
     digest = chunk_state[8]
     written = chunk_state[9]
     try:
         os.write(fd, file_data)
         digest.update(file_data)
         written += len(file_data)
         chunk_state[9] = written
     except OSError as e:
         filelog.error("Error: cannot write file chunk")
         filelog.error(" %s", e)
         self.send("ack-file-chunk", chunk_id, False, "write error: %s" % e, chunk)
         del self.receive_chunks_in_progress[chunk_id]
         try:
             os.close(fd)
         except (OSError, IOError):
             pass
         return
     self.send("ack-file-chunk", chunk_id, True, "", chunk)
     if has_more:
         timer = chunk_state[-2]
         if timer:
             self.source_remove(timer)
         #remote end will send more after receiving the ack
         timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_receiving, chunk_id, chunk)
         chunk_state[-2] = timer
         return
     del self.receive_chunks_in_progress[chunk_id]
     os.close(fd)
     #check file size and digest then process it:
     filename, mimetype, printit, openit, filesize, options = chunk_state[2:8]
     if written!=filesize:
         filelog.error("Error: expected a file of %i bytes, got %i", filesize, written)
         return
     expected_digest = options.get("sha1")
     if expected_digest:
         self.check_digest(filename, digest.hexdigest(), expected_digest)
     start_time = chunk_state[0]
     elapsed = monotonic_time()-start_time
     mimetype = bytestostr(mimetype)
     filelog("%i bytes received in %i chunks, took %ims", filesize, chunk, elapsed*1000)
     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)
Example #24
0
def get_lpinfo_drv(make_and_model):
    command = shlex.split(LPINFO)+["--make-and-model", make_and_model, "-m"]
    def preexec():
        os.setsid()
    log("get_lpinfo_drv(%s) command=%s", make_and_model, command)
    try:
        proc = subprocess.Popen(command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, close_fds=True, preexec_fn=preexec)
    except Exception as e:
        log("get_lp_info_drv(%s) lpinfo command %s failed", make_and_model, command, exc_info=True)
        log.error("Error: lpinfo command failed to run")
        log.error(" %s", e)
        log.error(" command used: '%s'", " ".join(command))
        return None
    #use the global child reaper to make sure this doesn't end up as a zombie
    from xpra.child_reaper import getChildReaper
    from xpra.util import nonl
    cr = getChildReaper()
    cr.add_process(proc, "lpinfo", command, ignore=True, forget=True)
    from xpra.make_thread import start_thread
    def watch_lpinfo():
        #give it 15 seconds to run:
        for _ in range(15):
            if proc.poll() is not None:
                return      #finished already
            time.sleep(1)
        log.warn("Warning: lpinfo command is taking too long")
        proc.terminate()
    start_thread(watch_lpinfo, "lpinfo watcher", daemon=True)
    out, err = proc.communicate()
    if proc.wait()!=0:
        log.warn("Warning: lpinfo command failed and returned %s", proc.returncode)
        log.warn(" command used: '%s'", " ".join(command))
        return None
    if sys.version_info[0]>=3:
        try:
            out = out.decode()
        except:
            out = str(out)
    log("lpinfo out=%s", nonl(out))
    log("lpinfo err=%s", nonl(err))
    if err:
        log.warn("Warning: lpinfo command produced some warnings:")
        log.warn(" '%s'", nonl(err))
    for line in out.splitlines():
        if line.startswith("drv://"):
            return line.split(" ")[0]
    return None
Example #25
0
 def __init__(self, sock, process_packet_cb):
     assert sock is not None
     self._closed = False
     self._socket = sock
     self._process_packet_cb = process_packet_cb
     self._read_thread = start_thread(self._read_thread_loop,
                                      "read",
                                      daemon=True)
Example #26
0
 def threaded_setup(self):
     self.exec_start_commands()
     def set_reaper_callback():
         self.child_reaper.set_quit_callback(self.reaper_exit)
         self.child_reaper.check()
     self.idle_add(set_reaper_callback)
     if POSIX and not OSX and self.start_new_commands and EXPORT_XDG_MENU_DATA:
         try:
             self.setup_menu_watcher()
         except Exception as e:
             log("threaded_setup()", exc_info=True)
             log.error("Error setting up menu watcher:")
             log.error(" %s", e)
         from xpra.platform.xposix.xdg_helper import load_xdg_menu_data
         #start loading in a thread,
         #so server startup can complete:
         start_thread(load_xdg_menu_data, "load-xdg-menu-data", True)
Example #27
0
 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)
     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)
Example #28
0
 def process_downloaded_file(self, filename, mimetype, printit, openit,
                             filesize, options):
     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)
Example #29
0
 def start(self):
     if self.last_UI_thread_time>0:
         log.warn("UI thread watcher already started!")
         return
     #run once to initialize:
     self.UI_thread_wakeup()
     if self.polling_timeout>0:
         start_thread(self.poll_UI_loop, "UI thread polling")
     else:
         log("not starting an IO polling thread")
     if FAKE_UI_LOCKUPS>0:
         #watch out: sleeping in UI thread!
         def sleep_in_ui_thread(*args):
             t = threading.current_thread()
             log.warn("sleep_in_ui_thread%s pausing %s for %ims", args, t, FAKE_UI_LOCKUPS)
             time.sleep(FAKE_UI_LOCKUPS/1000.0)
             return True
         self.timeout_add(10*1000+FAKE_UI_LOCKUPS, sleep_in_ui_thread)
Example #30
0
    def run(self):
        from xpra.make_thread import start_thread
        start_thread(self.read_stdin, "read-stdin", True)
        self.show_all()
        force_focus()
        self.present()
        self.timeout_timer = GLib.timeout_add(TIMEOUT * 1000, self.timeout)
        self.pulse_timer = GLib.timeout_add(100, self.pulse)
        scrash = envint("XPRA_SPLASH_CRASH", -1)
        if scrash >= 0:

            def crash():
                import ctypes  #pylint: disable=import-outside-toplevel
                ctypes.string_at(0)

            GLib.timeout_add(scrash, crash)
        Gtk.main()
        return self.exit_code or 0
Example #31
0
 def start_queue_encode(self, item):
     #start the encode work queue:
     #holds functions to call to compress data (pixels, clipboard)
     #items placed in this queue are picked off by the "encode" thread,
     #the functions should add the packets they generate to the 'packet_queue'
     self.encode_work_queue = Queue()
     self.queue_encode = self.encode_work_queue.put
     self.queue_encode(item)
     self.encode_thread = start_thread(self.encode_loop, "encode")
Example #32
0
    def __init__(self):
        self.exit_code = None
        super().__init__()
        self.set_border_width(20)
        self.set_title("Start Desktop Environment")
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_size_request(640, 300)
        icon = get_icon_pixbuf("xpra.png")
        if icon:
            self.set_icon(icon)
        self.connect("delete-event", self.quit)
        add_close_accel(self, self.quit)

        vbox = Gtk.VBox(False, 0)
        vbox.set_spacing(10)

        #self.entry_label = l("Command:")
        #vbox.add(self.entry_label)
        self.desktop_combo = sf(Gtk.ComboBoxText())
        vbox.add(self.desktop_combo)

        # Action buttons:
        hbox = Gtk.HBox(False, 20)
        vbox.pack_start(hbox, False, True, 20)

        def btn(label, tooltip, callback, default=False):
            ib = imagebutton(label,
                             tooltip=tooltip,
                             clicked_callback=callback,
                             icon_size=32,
                             default=default,
                             label_font=Pango.FontDescription("sans 16"))
            hbox.pack_start(ib)
            return ib

        self.cancel_btn = btn("Exit", "", self.quit)
        self.run_btn = btn("Start", "Start the desktop environment",
                           self.run_command)

        vbox.show_all()
        self.add(vbox)
        start_thread(self.load_desktop_session,
                     "load-desktop-sessions",
                     daemon=True)
Example #33
0
    def start_proxy(self, client_proto, c, auth_caps):
        def disconnect(reason, *extras):
            log("disconnect(%s, %s)", reason, extras)
            self.send_disconnect(client_proto, reason, *extras)

        #find the target server session:
        if not client_proto.authenticator:
            log.error("Error: the proxy server requires an authentication mode,")
            try:
                log.error(" client connection '%s' does not specify one", client_proto._conn.socktype)
            except:
                pass
            log.error(" use 'none' to disable authentication")
            disconnect(SESSION_NOT_FOUND, "no sessions found")
            return
        try:
            sessions = client_proto.authenticator.get_sessions()
        except Exception as e:
            authlog("failed to get the list of sessions", exc_info=True)
            authlog.error("Error: failed to get the list of sessions using '%s' authenticator", client_proto.authenticator)
            authlog.error(" %s", e)
            disconnect(AUTHENTICATION_ERROR, "cannot access sessions")
            return
        authlog("start_proxy(%s, {..}, %s) found sessions: %s", client_proto, auth_caps, sessions)
        if sessions is None:
            disconnect(SESSION_NOT_FOUND, "no sessions found")
            return
        uid, gid, displays, env_options, session_options = sessions
        if os.name=="posix":
            if uid==0 or gid==0:
                log.error("Error: proxy instances should not run as root")
                log.error(" use a different uid and gid (ie: nobody)")
                disconnect(AUTHENTICATION_ERROR, "cannot run proxy instances as root")
                return
            username = get_username_for_uid(uid)
            groups = get_groups(username)
            if "xpra" not in groups:
                log.error("Error: user '%s' (uid=%i) is not in the xpra group", username, uid)
                log.error(" it belongs to: %s", csv(groups) or None)
                disconnect(PERMISSION_ERROR, "user missing 'xpra' group membership")
                return
        #ensure we don't loop back to the proxy:
        proxy_virtual_display = os.environ.get("DISPLAY")
        if proxy_virtual_display in displays:
            displays.remove(proxy_virtual_display)
        #remove proxy instance virtual displays:
        displays = [x for x in displays if not x.startswith(":proxy-")]
        #log("unused options: %s, %s", env_options, session_options)
        opts = make_defaults_struct()
        display = None
        proc = None
        sns = c.dictget("start-new-session")
        authlog("start_proxy: displays=%s, start-new-session=%s", displays, bool(sns))
        if len(displays)==0 or sns:
            if self._start_sessions:
                #start a new session
                mode = sns.get("mode", "start")
                assert mode in ("start", "start-desktop", "shadow"), "invalid start-new-session mode '%s'" % mode
                sns = typedict(sns)
                display = sns.get("display")
                args = []
                if display:
                    args = [display]
                start = sns.strlistget("start")
                start_child = sns.strlistget("start-child")
                exit_with_children = sns.boolget("exit-with-children")
                exit_with_client = sns.boolget("exit-with-client")
                log("starting new server subprocess: mode=%s, socket-dir=%s, socket-dirs=%s, start=%s, start-child=%s, exit-with-children=%s, exit-with-client=%s, uid=%s, gid=%s",
                    mode, opts.socket_dir, opts.socket_dirs, start, start_child, exit_with_children, exit_with_client, uid, gid)
                try:
                    proc, socket_path = start_server_subprocess(sys.argv[0], args, mode, opts,
                                                                opts.socket_dir, opts.socket_dirs,
                                                                start, start_child,
                                                                exit_with_children, exit_with_client,
                                                                uid=uid, gid=gid)
                    display = "socket:%s" % socket_path
                except Exception as e:
                    log("start_server_subprocess failed", exc_info=True)
                    log.error("Error: failed to start server subprocess:")
                    log.error(" %s", e)
                    disconnect(SERVER_ERROR, "failed to start a new session")
                    return
                if proc:
                    self.child_reaper.add_process(proc, "server-%s" % display, "xpra start", True, True)
            else:
                disconnect(SESSION_NOT_FOUND, "no displays found")
                return
        if display is None:
            display = c.strget("display")
            authlog("start_proxy: proxy-virtual-display=%s (ignored), user specified display=%s, found displays=%s", proxy_virtual_display, display, displays)
            if display==proxy_virtual_display:
                disconnect(SESSION_NOT_FOUND, "invalid display")
                return
            if display:
                if display not in displays:
                    disconnect(SESSION_NOT_FOUND, "display '%s' not found" % display)
                    return
            else:
                if len(displays)!=1:
                    disconnect(SESSION_NOT_FOUND, "please specify a display, more than one is available: %s" % csv(displays))
                    return
                display = displays[0]

        def stop_server_subprocess():
            if proc:
                proc.terminate()

        log("start_proxy(%s, {..}, %s) using server display at: %s", client_proto, auth_caps, display)
        def parse_error(*args):
            stop_server_subprocess()
            disconnect(SESSION_NOT_FOUND, "invalid display string")
            log.warn("Error: parsing failed for display string '%s':", display)
            for arg in args:
                log.warn(" %s", arg)
            raise Exception("parse error on %s: %s" % (display, args))
        opts.username = client_proto.authenticator.username
        disp_desc = parse_display_name(parse_error, opts, display)
        if uid or gid:
            disp_desc["uid"] = uid
            disp_desc["gid"] = gid
        log("display description(%s) = %s", display, disp_desc)
        try:
            server_conn = connect_to(disp_desc, opts)
        except Exception as e:
            log("cannot connect", exc_info=True)
            log.error("Error: cannot start proxy connection:")
            log.error(" %s", e)
            log.error(" connection definition:")
            print_nested_dict(disp_desc, prefix=" ", lchar="*", pad=20, print_fn=log.error)
            disconnect(SESSION_NOT_FOUND, "failed to connect to display")
            stop_server_subprocess()
            return
        log("server connection=%s", server_conn)

        #no other packets should be arriving until the proxy instance responds to the initial hello packet
        def unexpected_packet(packet):
            if packet:
                log.warn("Warning: received an unexpected packet on the proxy connection %s:", client_proto)
                log.warn(" %s", repr_ellipsized(packet))
        client_conn = client_proto.steal_connection(unexpected_packet)
        client_state = client_proto.save_state()
        cipher = None
        encryption_key = None
        if auth_caps:
            cipher = auth_caps.get("cipher")
            if cipher:
                encryption_key = self.get_encryption_key(client_proto.authenticator, client_proto.keyfile)
        log("start_proxy(..) client connection=%s", client_conn)
        log("start_proxy(..) client state=%s", client_state)

        #this may block, so run it in a thread:
        def do_start_proxy():
            log("do_start_proxy()")
            message_queue = MQueue()
            try:
                ioe = client_proto.wait_for_io_threads_exit(5+self._socket_timeout)
                if not ioe:
                    log.error("Error: some network IO threads have failed to terminate")
                    return
                client_conn.set_active(True)
                process = ProxyInstanceProcess(uid, gid, env_options, session_options, self._socket_dir,
                                               self.video_encoders, self.csc_modules,
                                               client_conn, client_state, cipher, encryption_key, server_conn, c, message_queue)
                log("starting %s from pid=%s", process, os.getpid())
                self.processes[process] = (display, message_queue)
                process.start()
                log("process started")
                popen = process._popen
                assert popen
                #when this process dies, run reap to update our list of proxy processes:
                self.child_reaper.add_process(popen, "xpra-proxy-%s" % display, "xpra-proxy-instance", True, True, self.reap)
            finally:
                #now we can close our handle on the connection:
                client_conn.close()
                server_conn.close()
                message_queue.put("socket-handover-complete")
        start_thread(do_start_proxy, "start_proxy(%s)" % client_conn)