Пример #1
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 make_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()

    make_thread(watch_lpinfo, "lpinfo watcher", daemon=True).start()
    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
Пример #2
0
 def __init__(self, client, opts):
     self.client = client
     self._kh_warning = False
     self._console_handler_registered = self.setup_console_event_listener(
         True)
     try:
         el = get_win32_event_listener(True)
         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)
     except Exception as e:
         log.error("cannot register focus and power callbacks: %s", e)
     self.keyboard_hook_id = None
     if FORWARD_WINDOWS_KEY:
         from xpra.make_thread import make_thread
         make_thread(self.init_keyboard_listener,
                     "keyboard-listener",
                     daemon=True).start()
Пример #3
0
 def __init__(self, scheduler, conn, process_packet_cb, get_packet_cb=None):
     """
         You must call this constructor and source_has_more() from the main thread.
     """
     assert scheduler is not None
     assert conn is not None
     self.timeout_add = scheduler.timeout_add
     self.idle_add = scheduler.idle_add
     self._conn = conn
     if FAKE_JITTER > 0:
         from xpra.net.fake_jitter import FakeJitter
         fj = FakeJitter(self.timeout_add, process_packet_cb)
         self._process_packet_cb = fj.process_packet_cb
     else:
         self._process_packet_cb = process_packet_cb
     self._write_queue = Queue(1)
     self._read_queue = Queue(20)
     self._read_queue_put = self.read_queue_put
     # Invariant: if .source is None, then _source_has_more == False
     self._get_packet_cb = get_packet_cb
     #counters:
     self.input_stats = {}
     self.input_packetcount = 0
     self.input_raw_packetcount = 0
     self.output_stats = {}
     self.output_packetcount = 0
     self.output_raw_packetcount = 0
     #initial value which may get increased by client/server after handshake:
     self.max_packet_size = 256 * 1024
     self.abs_max_packet_size = 256 * 1024 * 1024
     self.large_packets = ["hello", "window-metadata", "sound-data"]
     self.send_aliases = {}
     self.receive_aliases = {}
     self._log_stats = None  #None here means auto-detect
     self._closed = False
     self.encoder = "none"
     self._encoder = self.noencode
     self.compressor = "none"
     self._compress = compression.nocompress
     self.compression_level = 0
     self.cipher_in = None
     self.cipher_in_name = None
     self.cipher_in_block_size = 0
     self.cipher_in_padding = INITIAL_PADDING
     self.cipher_out = None
     self.cipher_out_name = None
     self.cipher_out_block_size = 0
     self.cipher_out_padding = INITIAL_PADDING
     self._write_lock = Lock()
     from xpra.make_thread import make_thread
     self._write_thread = make_thread(self._write_thread_loop,
                                      "write",
                                      daemon=True)
     self._read_thread = make_thread(self._read_thread_loop,
                                     "read",
                                     daemon=True)
     self._read_parser_thread = None  #started when needed
     self._write_format_thread = None  #started when needed
     self._source_has_more = Event()
Пример #4
0
 def invalid_header(self, proto, data):
     netlog("invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy)
     if proto.input_packetcount==0 and self._tcp_proxy and not proto._closed:
         #start a new proxy in a thread
         def run_proxy():
             self.start_tcp_proxy(proto, data)
         make_thread(run_proxy, "web-proxy-for-%s" % proto).start()
         return
     err = "invalid packet format, not an xpra client?"
     proto.gibberish(err, data)
Пример #5
0
 def __init__(self, scheduler, conn, process_packet_cb, get_packet_cb=None):
     """
         You must call this constructor and source_has_more() from the main thread.
     """
     assert scheduler is not None
     assert conn is not None
     self.timeout_add = scheduler.timeout_add
     self.idle_add = scheduler.idle_add
     self._conn = conn
     if FAKE_JITTER>0:
         from xpra.net.fake_jitter import FakeJitter
         fj = FakeJitter(self.timeout_add, process_packet_cb)
         self._process_packet_cb =  fj.process_packet_cb
     else:
         self._process_packet_cb = process_packet_cb
     self._write_queue = Queue(1)
     self._read_queue = Queue(20)
     self._read_queue_put = self.read_queue_put
     # Invariant: if .source is None, then _source_has_more == False
     self._get_packet_cb = get_packet_cb
     #counters:
     self.input_stats = {}
     self.input_packetcount = 0
     self.input_raw_packetcount = 0
     self.output_stats = {}
     self.output_packetcount = 0
     self.output_raw_packetcount = 0
     #initial value which may get increased by client/server after handshake:
     self.max_packet_size = 256*1024
     self.abs_max_packet_size = 256*1024*1024
     self.large_packets = ["hello", "window-metadata"]
     self.send_aliases = {}
     self.receive_aliases = {}
     self._log_stats = None          #None here means auto-detect
     self._closed = False
     self.encoder = "none"
     self._encoder = self.noencode
     self.compressor = "none"
     self._compress = compression.nocompress
     self.compression_level = 0
     self.cipher_in = None
     self.cipher_in_name = None
     self.cipher_in_block_size = 0
     self.cipher_in_padding = INITIAL_PADDING
     self.cipher_out = None
     self.cipher_out_name = None
     self.cipher_out_block_size = 0
     self.cipher_out_padding = INITIAL_PADDING
     self._write_lock = Lock()
     from xpra.make_thread import make_thread
     self._write_thread = make_thread(self._write_thread_loop, "write", daemon=True)
     self._read_thread = make_thread(self._read_thread_loop, "read", daemon=True)
     self._read_parser_thread = None         #started when needed
     self._write_format_thread = None        #started when needed
     self._source_has_more = Event()
Пример #6
0
 def get_all_info(self, callback, proto, *args):
     ui_info = self.get_ui_info(proto, *args)
     def in_thread(*args):
         #this runs in a non-UI thread
         try:
             info = self.get_info(proto, *args)
             ui_info.update(info)
         except Exception as e:
             log.error("error during info collection: %s", e, exc_info=True)
         callback(proto, ui_info)
     make_thread(in_thread, "Info", daemon=True).start()
Пример #7
0
    def get_all_info(self, callback, proto, *args):
        ui_info = self.get_ui_info(proto, *args)

        def in_thread(*args):
            #this runs in a non-UI thread
            try:
                info = self.get_info(proto, *args)
                ui_info.update(info)
            except Exception as e:
                log.error("error during info collection: %s", e, exc_info=True)
            callback(proto, ui_info)

        make_thread(in_thread, "Info", daemon=True).start()
Пример #8
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 = self.setup_console_event_listener(
                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)
        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:
            from xpra.make_thread import make_thread
            make_thread(self.init_keyboard_listener,
                        "keyboard-listener",
                        daemon=True).start()
Пример #9
0
    def invalid_header(self, proto, data):
        netlog(
            "invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s",
            proto, len(data or ""), repr_ellipsized(data),
            proto.input_packetcount, self._tcp_proxy)
        if proto.input_packetcount == 0 and self._tcp_proxy and not proto._closed:
            #start a new proxy in a thread
            def run_proxy():
                self.start_tcp_proxy(proto, data)

            make_thread(run_proxy, "web-proxy-for-%s" % proto).start()
            return
        err = "invalid packet format, not an xpra client?"
        proto.gibberish(err, data)
Пример #10
0
 def __init__(self,
              scheduler,
              conn,
              auth,
              process_packet_cb,
              get_rfb_pixelformat,
              session_name="Xpra"):
     """
         You must call this constructor and source_has_more() from the main thread.
     """
     assert scheduler is not None
     assert conn is not None
     self.timeout_add = scheduler.timeout_add
     self.idle_add = scheduler.idle_add
     self._conn = conn
     self._authenticator = auth
     self._process_packet_cb = process_packet_cb
     self._get_rfb_pixelformat = get_rfb_pixelformat
     self.session_name = session_name
     self._write_queue = Queue()
     self._buffer = b""
     self._challenge = None
     self.share = False
     #counters:
     self.input_packetcount = 0
     self.input_raw_packetcount = 0
     self.output_packetcount = 0
     self.output_raw_packetcount = 0
     self._protocol_version = ()
     self._closed = False
     self._packet_parser = self._parse_protocol_handshake
     self._write_thread = None
     self._read_thread = make_thread(self._read_thread_loop,
                                     "read",
                                     daemon=True)
Пример #11
0
 def read_queue_put(self, data):
     #start the parse thread if needed:
     if not self._read_parser_thread and not self._closed:
         self._read_parser_thread = make_thread(
             self._read_parse_thread_loop, "parse", daemon=True)
         self._read_parser_thread.start()
     self._read_queue.put(data)
Пример #12
0
 def read_queue_put(self, data):
     #start the parse thread if needed:
     if not self._read_parser_thread and not self._closed:
         from xpra.make_thread import make_thread
         self._read_parser_thread = make_thread(self._read_parse_thread_loop, "parse", daemon=True)
         self._read_parser_thread.start()
     self._read_queue.put(data)
Пример #13
0
 def __init__(self, scheduler, conn, process_packet_cb, data=b""):
     assert scheduler is not None
     assert conn is not None
     self.timeout_add = scheduler.timeout_add
     self.idle_add = scheduler.idle_add
     self._conn = conn
     self._process_packet_cb = process_packet_cb
     self._write_queue = Queue()
     self._buffer = data
     self._challenge = None
     self.share = False
     #counters:
     self.input_packetcount = 0
     self.input_raw_packetcount = 0
     self.output_packetcount = 0
     self.output_raw_packetcount = 0
     self._closed = False
     self._packet_parser = self._parse_protocol_handshake
     self._write_thread = None
     self._read_thread = make_thread(self._read_thread_loop,
                                     "read",
                                     daemon=True)
     self.log = None
     if RFB_LOG:
         self.log = open(RFB_LOG, "w")
Пример #14
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 make_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()
    make_thread(watch_lpinfo, "lpinfo watcher", daemon=True).start()
    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
Пример #15
0
 def source_has_more(self):
     self._source_has_more.set()
     #start the format thread:
     if not self._write_format_thread and not self._closed:
         self._write_format_thread = make_thread(
             self._write_format_thread_loop, "format", daemon=True)
         self._write_format_thread.start()
     INJECT_FAULT(self)
Пример #16
0
 def get_all_info(self, callback, proto=None, *args):
     start = time.time()
     ui_info = self.get_ui_info(proto, *args)
     end = time.time()
     log("get_all_info: ui info collected in %ims", (end-start)*1000)
     def in_thread(*args):
         start = time.time()
         #this runs in a non-UI thread
         try:
             info = self.get_info(proto, *args)
             merge_dicts(ui_info, info)
         except Exception as e:
             log.error("error during info collection: %s", e, exc_info=True)
         end = time.time()
         log("get_all_info: non ui info collected in %ims", (end-start)*1000)
         callback(proto, ui_info)
     make_thread(in_thread, "Info", daemon=True).start()
Пример #17
0
 def source_has_more(self):
     self._source_has_more.set()
     #start the format thread:
     if not self._write_format_thread and not self._closed:
         from xpra.make_thread import make_thread
         self._write_format_thread = make_thread(self._write_format_thread_loop, "format", daemon=True)
         self._write_format_thread.start()
     INJECT_FAULT(self)
Пример #18
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:
         make_thread(self.poll_UI_loop, "UI thread polling").start()
     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)
Пример #19
0
 def __init__(self, client, opts):
     self.client = client
     self._kh_warning = False
     self._console_handler_registered = self.setup_console_event_listener(True)
     try:
         el = get_win32_event_listener(True)
         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)
     except Exception as e:
         log.error("cannot register focus and power callbacks: %s", e)
     self.keyboard_hook_id = None
     if FORWARD_WINDOWS_KEY:
         from xpra.make_thread import make_thread
         make_thread(self.init_keyboard_listener, "keyboard-listener", daemon=True).start()
Пример #20
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:
            make_thread(self.poll_UI_loop, "UI thread polling").start()
        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)
Пример #21
0
 def source_has_more(self):
     shm = self._source_has_more
     if not shm or self._closed:
         return
     shm.set()
     #start the format thread:
     if not self._write_format_thread and not self._closed:
         self._write_format_thread = make_thread(self._write_format_thread_loop, "format", daemon=True)
         self._write_format_thread.start()
     #from now on, take shortcut:
     self.source_has_more = self._source_has_more.set
Пример #22
0
    def get_all_info(self, callback, proto=None, *args):
        start = time.time()
        ui_info = self.get_ui_info(proto, *args)
        end = time.time()
        log("get_all_info: ui info collected in %ims", (end - start) * 1000)

        def in_thread(*args):
            start = time.time()
            #this runs in a non-UI thread
            try:
                info = self.get_info(proto, *args)
                merge_dicts(ui_info, info)
            except Exception as e:
                log.error("error during info collection: %s", e, exc_info=True)
            end = time.time()
            log("get_all_info: non ui info collected in %ims",
                (end - start) * 1000)
            callback(proto, ui_info)

        make_thread(in_thread, "Info", daemon=True).start()
Пример #23
0
    def run(self):
        log("ProxyProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(),
            os.getuid(), os.getgid())
        #change uid and gid:
        if os.getgid() != self.gid:
            os.setgid(self.gid)
        if os.getuid() != self.uid:
            os.setuid(self.uid)
        log("ProxyProcess.run() new uid=%s, gid=%s", os.getuid(), os.getgid())

        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)

        make_thread(self.server_message_queue, "server message queue").start()

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

        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.server_protocol.large_packets.append("send-file")
        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 = make_thread(self.encode_loop, "encode")
        self.encode_thread.start()

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

        #forward the hello packet:
        hello_packet = ("hello", self.filter_client_caps(self.caps))
        self.queue_server_packet(hello_packet)
        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())
Пример #24
0
    def start_proxy(self, client_proto, c, auth_caps):
        assert client_proto.authenticator is not None
        #find the target server session:
        def disconnect(reason, *extras):
            self.send_disconnect(client_proto, reason, *extras)
        try:
            sessions = client_proto.authenticator.get_sessions()
        except Exception as e:
            log.error("failed to get the list of sessions: %s", e)
            disconnect(AUTHENTICATION_ERROR)
            return
        if sessions is None:
            disconnect(SESSION_NOT_FOUND, "no sessions found")
            return
        log("start_proxy(%s, {..}, %s) found sessions: %s", client_proto, auth_caps, sessions)
        uid, gid, displays, env_options, session_options = sessions
        #log("unused options: %s, %s", env_options, session_options)
        if len(displays)==0:
            disconnect(SESSION_NOT_FOUND, "no displays found")
            return
        display = c.strget("display")
        proxy_virtual_display = os.environ.get("DISPLAY")
        #ensure we don't loop back to the proxy:
        if proxy_virtual_display in displays:
            displays.remove(proxy_virtual_display)
        if display==proxy_virtual_display:
            disconnect(SESSION_NOT_FOUND, "invalid display")
            return
        if display:
            if display not in displays:
                disconnect(SESSION_NOT_FOUND, "display not found")
                return
        else:
            if len(displays)!=1:
                disconnect(SESSION_NOT_FOUND, "please specify a display (more than one available)")
                return
            display = displays[0]

        log("start_proxy(%s, {..}, %s) using server display at: %s", client_proto, auth_caps, display)
        def parse_error(*args):
            disconnect(SESSION_NOT_FOUND, "invalid display string")
            log.warn("parse error on %s: %s", display, args)
            raise Exception("parse error on %s: %s" % (display, args))
        opts = make_defaults_struct()
        opts.username = client_proto.authenticator.username
        disp_desc = parse_display_name(parse_error, opts, display)
        log("display description(%s) = %s", display, disp_desc)
        try:
            server_conn = connect_to(disp_desc)
        except Exception as e:
            log.error("cannot start proxy connection to %s: %s", disp_desc, e, exc_info=True)
            disconnect(SESSION_NOT_FOUND, "failed to connect to display")
            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("received an unexpected packet on the proxy connection: %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("some network IO threads have failed to terminate!")
                    return
                client_conn.set_active(True)
                assert uid!=0 and gid!=0
                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")
            finally:
                #now we can close our handle on the connection:
                client_conn.close()
                server_conn.close()
                message_queue.put("socket-handover-complete")
            #FIXME: remove processes that have terminated
        make_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start()
Пример #25
0
    def run(self):
        log("ProxyProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), os.getuid(), os.getgid())
        #change uid and gid:
        if os.getgid()!=self.gid:
            os.setgid(self.gid)
        if os.getuid()!=self.uid:
            os.setuid(self.uid)
        log("ProxyProcess.run() new uid=%s, gid=%s", os.getuid(), os.getgid())

        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)

        make_thread(self.server_message_queue, "server message queue").start()

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

        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.server_protocol.large_packets.append("send-file")
        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 = make_thread(self.encode_loop, "encode")
        self.encode_thread.start()

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

        #forward the hello packet:
        hello_packet = ("hello", self.filter_client_caps(self.caps))
        self.queue_server_packet(hello_packet)
        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())
Пример #26
0
    def start_proxy(self, client_proto, c, auth_caps):
        assert client_proto.authenticator is not None
        #find the target server session:
        def disconnect(reason, *extras):
            self.send_disconnect(client_proto, reason, *extras)
        try:
            sessions = client_proto.authenticator.get_sessions()
        except Exception as e:
            log.error("failed to get the list of sessions: %s", e)
            disconnect(AUTHENTICATION_ERROR)
            return
        if sessions is None:
            disconnect(SESSION_NOT_FOUND, "no sessions found")
            return
        log("start_proxy(%s, {..}, %s) found sessions: %s", client_proto, auth_caps, sessions)
        uid, gid, displays, env_options, session_options = sessions
        #log("unused options: %s, %s", env_options, session_options)
        if len(displays)==0:
            disconnect(SESSION_NOT_FOUND, "no displays found")
            return
        display = c.strget("display")
        proxy_virtual_display = os.environ.get("DISPLAY")
        #ensure we don't loop back to the proxy:
        if proxy_virtual_display in displays:
            displays.remove(proxy_virtual_display)
        if display==proxy_virtual_display:
            disconnect(SESSION_NOT_FOUND, "invalid display")
            return
        if display:
            if display not in displays:
                disconnect(SESSION_NOT_FOUND, "display not found")
                return
        else:
            if len(displays)!=1:
                disconnect(SESSION_NOT_FOUND, "please specify a display (more than one available)")
                return
            display = displays[0]

        log("start_proxy(%s, {..}, %s) using server display at: %s", client_proto, auth_caps, display)
        def parse_error(*args):
            disconnect(SESSION_NOT_FOUND, "invalid display string")
            log.warn("parse error on %s: %s", display, args)
            raise Exception("parse error on %s: %s" % (display, args))
        opts = make_defaults_struct()
        opts.username = client_proto.authenticator.username
        disp_desc = parse_display_name(parse_error, opts, display)
        log("display description(%s) = %s", display, disp_desc)
        try:
            server_conn = connect_to(disp_desc)
        except Exception as e:
            log.error("cannot start proxy connection to %s: %s", disp_desc, e, exc_info=True)
            disconnect(SESSION_NOT_FOUND, "failed to connect to display")
            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("received an unexpected packet on the proxy connection: %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(0.5+self._socket_timeout)
                if not ioe:
                    log.error("some network IO threads have failed to terminate!")
                    return
                client_conn.set_active(True)
                assert uid!=0 and gid!=0
                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")
            finally:
                #now we can close our handle on the connection:
                client_conn.close()
                server_conn.close()
                message_queue.put("socket-handover-complete")
            #FIXME: remove processes that have terminated
        make_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start()