예제 #1
0
 def server_connection_established(self, caps: typedict):
     #the server should respond with the display chosen
     log("server_connection_established() exit_code=%s", self.exit_code)
     display = caps.strget("display")
     if display:
         mode = caps.strget("mode")
         session_type = {
             "start": "seamless ",
             "start-desktop": "desktop ",
             "shadow": "shadow ",
         }.get(mode, "")
         try:
             errwrite("\n%ssession now available on display %s\n" %
                      (session_type, display))
             if POSIX and not OSX and self.displayfd > 0 and display and display.startswith(
                     b":"):
                 from xpra.platform.displayfd import write_displayfd
                 log("writing display %s to displayfd=%s", display,
                     self.displayfd)
                 write_displayfd(self.displayfd, display[1:])
         except OSError:
             log("server_connection_established(..)", exc_info=True)
     if not self.exit_code:
         self.quit(0)
     return True
예제 #2
0
 def process_ui_capabilities(self, c : typedict):
     self.server_is_desktop = c.boolget("shadow") or c.boolget("desktop")
     skip_vfb_size_check = False           #if we decide not to use scaling, skip warnings
     if not fequ(self.xscale, 1.0) or not fequ(self.yscale, 1.0):
         #scaling is used, make sure that we need it and that the server can support it
         #(without rounding support, size-hints can cause resize loops)
         if self.server_is_desktop and not self.desktop_fullscreen:
             #don't honour auto mode in this case
             if self.desktop_scaling=="auto":
                 log.info(" not scaling a %s server", c.strget("type", "shadow"))
                 skip_vfb_size_check = self.xscale>1 or self.yscale>1
                 self.scale_change_embargo = 0
                 self.scalingoff()
     if self.can_scale:
         self.may_adjust_scaling()
     if not self.server_is_desktop and not skip_vfb_size_check and self.server_max_desktop_size:
         avail_w, avail_h = self.server_max_desktop_size
         root_w, root_h = self.get_root_size()
         log("validating server_max_desktop_size=%s vs root size=%s",
             self.server_max_desktop_size, (root_w, root_h))
         if self.cx(root_w)!=root_w or self.cy(root_h)!=root_h:
             log(" root size scaled to %s", (self.cx(root_w), self.cy(root_h)))
         if self.cx(root_w)>(avail_w+1) or self.cy(root_h)>(avail_h+1):
             log.warn("Server's virtual screen is too small")
             log.warn(" server: %sx%s vs client: %sx%s", avail_w, avail_h, self.cx(root_w), self.cy(root_h))
             log.warn(" you may see strange behavior,")
             log.warn(" please see https://github.com/Xpra-org/xpra/blob/master/docs/Usage/Xdummy.md")
     #now that we have the server's screen info, allow scale changes:
     self.scale_change_embargo = 0
     self.set_max_packet_size()
예제 #3
0
 def is_needed(cls, caps: typedict) -> bool:
     #pre 2.3 clients;
     if caps.strget("mmap_file"):
         return True
     v = caps.rawget("mmap")
     #we should be receiving a dict with mmap attributes
     #(but pre v4 clients also send a boolean telling us if mmap is supported by the platform..)
     return isinstance(v, dict)
예제 #4
0
 def do_authenticate(self, caps: typedict) -> bool:
     if self.passed:
         log("invalid state: challenge has already been passed")
         return False
     if not caps:
         log("invalid state: no capabilities")
         return False
     if not self.challenge_sent:
         log("invalid state: challenge has not been sent yet!")
         return False
     challenge_response = caps.strget("challenge_response")
     client_salt = caps.strget("challenge_client_salt")
     #challenge has been sent already for this module
     if not challenge_response:
         log("invalid state: challenge already sent but no response found!")
         return False
     return self.authenticate_check(challenge_response, client_salt)
예제 #5
0
 def do_command(self, caps: typedict):
     v = caps.strget(b"version")
     if not v:
         self.warn_and_quit(
             EXIT_FAILURE, "server did not provide the version information")
     else:
         sys.stdout.write("%s\n" % (v, ))
         self.quit(EXIT_OK)
예제 #6
0
 def do_command(self, caps : typedict):
     if caps:
         ctr = caps.strget("connect_test_response")
         log("do_command(..) expected connect test response='%s', got '%s'", self.value, ctr)
         if ctr==self.value:
             self.quit(EXIT_OK)
         else:
             self.quit(EXIT_INTERNAL_ERROR)
     else:
         self.quit(EXIT_FAILURE)
예제 #7
0
 def parse_server_capabilities(self, c : typedict) -> bool:
     self.server_display = c.strget("display")
     self.server_desktop_size = c.intpair("desktop_size")
     log("server desktop size=%s", self.server_desktop_size)
     self.server_max_desktop_size = c.intpair("max_desktop_size", (2**15, 2**15))
     self.server_actual_desktop_size = c.intpair("actual_desktop_size")
     log("server actual desktop size=%s", self.server_actual_desktop_size)
     self.server_randr = c.boolget("resize_screen")
     log("server has randr: %s", self.server_randr)
     self.server_opengl = c.dictget("opengl")
     return True
예제 #8
0
파일: audio.py 프로젝트: DiGuoZhiMeng/Xpra
 def parse_server_capabilities(self, c: typedict) -> bool:
     self.server_av_sync = c.boolget("av-sync.enabled")
     avsynclog("av-sync: server=%s, client=%s", self.server_av_sync,
               self.av_sync)
     self.server_pulseaudio_id = c.strget("sound.pulseaudio.id")
     self.server_pulseaudio_server = c.strget("sound.pulseaudio.server")
     self.server_sound_decoders = c.strtupleget("sound.decoders")
     self.server_sound_encoders = c.strtupleget("sound.encoders")
     self.server_sound_receive = c.boolget("sound.receive")
     self.server_sound_send = c.boolget("sound.send")
     self.server_sound_bundle_metadata = c.boolget("sound.bundle-metadata")
     log(
         "pulseaudio id=%s, server=%s, sound decoders=%s, sound encoders=%s, receive=%s, send=%s",
         self.server_pulseaudio_id, self.server_pulseaudio_server,
         csv(self.server_sound_decoders), csv(self.server_sound_encoders),
         self.server_sound_receive, self.server_sound_send)
     if self.server_sound_send and self.speaker_enabled:
         self.start_receiving_sound()
     if self.server_sound_receive and self.microphone_enabled:
         self.start_sending_sound()
     return True
예제 #9
0
파일: audio.py 프로젝트: chewi/xpra
 def parse_server_capabilities(self, c: typedict) -> bool:
     self.server_av_sync = c.boolget("av-sync.enabled")
     avsynclog("av-sync: server=%s, client=%s", self.server_av_sync,
               self.av_sync)
     self.server_pulseaudio_id = c.strget("sound.pulseaudio.id")
     self.server_pulseaudio_server = c.strget("sound.pulseaudio.server")
     self.server_sound_decoders = c.strtupleget("sound.decoders")
     self.server_sound_encoders = c.strtupleget("sound.encoders")
     self.server_sound_receive = c.boolget("sound.receive")
     self.server_sound_send = c.boolget("sound.send")
     log(
         "pulseaudio id=%s, server=%s, sound decoders=%s, sound encoders=%s, receive=%s, send=%s",
         self.server_pulseaudio_id, self.server_pulseaudio_server,
         csv(self.server_sound_decoders), csv(self.server_sound_encoders),
         self.server_sound_receive, self.server_sound_send)
     if self.server_sound_send and self.speaker_enabled:
         self.show_progress(90, "starting speaker forwarding")
         self.start_receiving_sound()
     if self.server_sound_receive and self.microphone_enabled:
         #call via idle_add because we may query X11 properties
         #to find the pulseaudio server:
         GLib.idle_add(self.start_sending_sound)
     return True
예제 #10
0
 def parse_server_capabilities(self, c: typedict) -> bool:
     try:
         from xpra import clipboard
         assert clipboard
     except ImportError:
         log.warn("Warning: clipboard module is missing")
         self.clipboard_enabled = False
         return True
     self.server_clipboard = c.boolget("clipboard")
     self.server_clipboard_loop_uuids = c.dictget("clipboard.loop-uuids",
                                                  {})
     self.server_clipboard_direction = c.strget("clipboard-direction",
                                                "both")
     if self.server_clipboard_direction != self.client_clipboard_direction and self.server_clipboard_direction != "both":
         if self.client_clipboard_direction == "disabled":
             pass
         elif self.server_clipboard_direction == "disabled":
             log.warn(
                 "Warning: server clipboard synchronization is currently disabled"
             )
             self.client_clipboard_direction = "disabled"
         elif self.client_clipboard_direction == "both":
             log.warn(
                 "Warning: server only supports '%s' clipboard transfers",
                 self.server_clipboard_direction)
             self.client_clipboard_direction = self.server_clipboard_direction
         else:
             log.warn("Warning: incompatible clipboard direction settings")
             log.warn(" server setting: %s, client setting: %s",
                      self.server_clipboard_direction,
                      self.client_clipboard_direction)
     try:
         from xpra.clipboard.clipboard_core import ALL_CLIPBOARDS
     except ImportError:
         ALL_CLIPBOARDS = []
     self.server_clipboards = c.strtupleget("clipboards", ALL_CLIPBOARDS)
     log("server clipboard: supported=%s, direction=%s",
         self.server_clipboard, self.server_clipboard_direction)
     log("client clipboard: supported=%s, direction=%s",
         self.client_supports_clipboard, self.client_clipboard_direction)
     self.clipboard_enabled = self.client_supports_clipboard and self.server_clipboard
     log("parse_clipboard_caps() clipboard enabled=%s",
         self.clipboard_enabled)
     self.server_clipboard_contents_slice_fix = c.boolget(
         "clipboard.contents-slice-fix")
     self.server_clipboard_preferred_targets = c.strtupleget(
         "clipboard.preferred-targets", ())
     if not self.server_clipboard_contents_slice_fix:
         log.info("server clipboard does not include contents slice fix")
     return True
예제 #11
0
파일: clipboard.py 프로젝트: chewi/xpra
 def parse_server_capabilities(self, c : typedict) -> bool:
     try:
         from xpra import clipboard
         assert clipboard
     except ImportError:
         log.warn("Warning: clipboard module is missing")
         self.clipboard_enabled = False
         return True
     self.server_clipboard = c.boolget("clipboard")
     self.server_clipboard_direction = c.strget("clipboard-direction", "both")
     if self.server_clipboard_direction!=self.client_clipboard_direction and self.server_clipboard_direction!="both":
         if self.client_clipboard_direction=="disabled":
             pass
         elif self.server_clipboard_direction=="disabled":
             log.warn("Warning: server clipboard synchronization is currently disabled")
             self.client_clipboard_direction = "disabled"
         elif self.client_clipboard_direction=="both":
             log.warn("Warning: server only supports '%s' clipboard transfers", self.server_clipboard_direction)
             self.client_clipboard_direction = self.server_clipboard_direction
         else:
             log.warn("Warning: incompatible clipboard direction settings")
             log.warn(" server setting: %s, client setting: %s",
                      self.server_clipboard_direction, self.client_clipboard_direction)
     try:
         from xpra.clipboard.clipboard_core import ALL_CLIPBOARDS
     except ImportError:
         ALL_CLIPBOARDS = []
     self.server_clipboards = c.strtupleget("clipboards", ALL_CLIPBOARDS)
     log("server clipboard: supported=%s, direction=%s",
                  self.server_clipboard, self.server_clipboard_direction)
     log("client clipboard: supported=%s, direction=%s",
                  self.client_supports_clipboard, self.client_clipboard_direction)
     self.clipboard_enabled = self.client_supports_clipboard and self.server_clipboard
     self.server_clipboard_greedy = c.boolget("clipboard.greedy")
     self.server_clipboard_want_targets = c.boolget("clipboard.want_targets")
     self.server_clipboard_selections = c.strtupleget("clipboard.selections", CLIPBOARDS)
     self.server_clipboard_preferred_targets = c.strtupleget("clipboard.preferred-targets", ())
     log("server clipboard: greedy=%s, want_targets=%s, selections=%s",
         self.server_clipboard_greedy, self.server_clipboard_want_targets, self.server_clipboard_selections)
     log("parse_clipboard_caps() clipboard enabled=%s", self.clipboard_enabled)
     self.server_clipboard_preferred_targets = c.strtupleget("clipboard.preferred-targets", ())
     return True
예제 #12
0
    def parse_server_capabilities(self, c: typedict) -> bool:
        p = self._protocol
        if p.TYPE == "rfb":
            #only the xpra protocol provides the server info
            return True
        self._remote_machine_id = c.strget("machine_id")
        self._remote_uuid = c.strget("uuid")
        self._remote_version = c.strget("build.version", c.strget("version"))
        self._remote_revision = c.strget("build.revision",
                                         c.strget("revision"))
        mods = c.get("build.local_modifications")
        if mods and str(mods).find("dfsg") >= 0:  # pragma: no cover
            get_util_logger().warn(
                "Warning: the xpra server is running a buggy Debian version")
            get_util_logger().warn(
                " those are usually out of date and unstable")
        else:
            self._remote_modifications = c.intget("build.local_modifications",
                                                  0)
        self._remote_commit = c.strget("build.commit")
        self._remote_build_date = c.strget("build.date")
        self._remote_build_time = c.strget("build.time")
        self._remote_hostname = c.strget("hostname")
        self._remote_display = c.strget("display")
        self._remote_platform = c.strget("platform")
        self._remote_platform_release = c.strget("platform.release")
        self._remote_platform_platform = c.strget("platform.platform")
        self._remote_python_version = c.strget("python.version")
        self._remote_subcommands = c.strtupleget("subcommands")
        self._remote_server_log = c.strget("server-log")
        self._remote_lib_versions = get_remote_lib_versions(c)
        #linux distribution is a tuple of different types, ie: ('Linux Fedora' , 20, 'Heisenbug')
        pld = c.tupleget("platform.linux_distribution")
        if pld and len(pld) == 3:

            def san(v):
                if isinstance(v, int):
                    return v
                return bytestostr(v)

            self._remote_platform_linux_distribution = [san(x) for x in pld]
        verr = version_compat_check(self._remote_version)
        if verr is not None:
            self.warn_and_quit(
                EXIT_INCOMPATIBLE_VERSION,
                "incompatible remote version '%s': %s" %
                (self._remote_version, verr))
            return False
        return True
예제 #13
0
    def parse_client_caps(self, c: typedict):
        import os
        from xpra.os_util import WIN32
        from xpra.log import Logger
        log = Logger("mmap")
        self.mmap_client_namespace = c.boolget("mmap.namespace", False)
        sep = "." if self.mmap_client_namespace else "_"

        def mmapattr(k):
            return "mmap%s%s" % (sep, k)

        mmap_filename = c.strget(mmapattr("file"))
        if not mmap_filename:
            return
        mmap_size = c.intget(mmapattr("size"), 0)
        log("client supplied mmap_file=%s", mmap_filename)
        mmap_token = c.intget(mmapattr("token"))
        log("mmap supported=%s, token=%s", self.supports_mmap, mmap_token)
        if self.mmap_filename:
            log("using global server specified mmap file path: '%s'",
                self.mmap_filename)
            mmap_filename = self.mmap_filename
        if not self.supports_mmap:
            log("client enabled mmap but mmap mode is not supported",
                mmap_filename)
        elif WIN32 and mmap_filename.startswith("/"):
            log("mmap_file '%s' is a unix path", mmap_filename)
        elif not os.path.exists(mmap_filename):
            log("mmap_file '%s' cannot be found!", mmap_filename)
        else:
            from xpra.net.mmap_pipe import (
                init_server_mmap,
                read_mmap_token,
                write_mmap_token,
                DEFAULT_TOKEN_INDEX,
                DEFAULT_TOKEN_BYTES,
            )
            self.mmap, self.mmap_size = init_server_mmap(
                mmap_filename, mmap_size)
            log("found client mmap area: %s, %i bytes - min mmap size=%i",
                self.mmap, self.mmap_size, self.min_mmap_size)
            if self.mmap_size > 0:
                index = c.intget(mmapattr("token_index"), DEFAULT_TOKEN_INDEX)
                count = c.intget(mmapattr("token_bytes"), DEFAULT_TOKEN_BYTES)
                v = read_mmap_token(self.mmap, index, count)
                log("mmap_token=%#x, verification=%#x", mmap_token, v)
                if v != mmap_token:
                    log.warn(
                        "Warning: mmap token verification failed, not using mmap area!"
                    )
                    log.warn(" expected '%#x', found '%#x'", mmap_token, v)
                    self.mmap.close()
                    self.mmap = None
                    self.mmap_size = 0
                elif self.mmap_size < self.min_mmap_size:
                    log.warn(
                        "Warning: client supplied mmap area is too small, discarding it"
                    )
                    log.warn(" we need at least %iMB and this area is %iMB",
                             self.min_mmap_size // 1024 // 1024,
                             self.mmap_size // 1024 // 1024)
                    self.mmap.close()
                    self.mmap = None
                    self.mmap_size = 0
                else:
                    from xpra.os_util import get_int_uuid
                    self.mmap_client_token = get_int_uuid()
                    self.mmap_client_token_bytes = DEFAULT_TOKEN_BYTES
                    if c.intget("mmap_token_index"):
                        #we can write the token anywhere we want and tell the client,
                        #so write it right at the end:
                        self.mmap_client_token_index = self.mmap_size - self.mmap_client_token_bytes
                    else:
                        #use the expected default for older versions:
                        self.mmap_client_token_index = DEFAULT_TOKEN_INDEX
                    write_mmap_token(self.mmap, self.mmap_client_token,
                                     self.mmap_client_token_index,
                                     self.mmap_client_token_bytes)
        if self.mmap_size > 0:
            from xpra.simple_stats import std_unit
            log.info(" mmap is enabled using %sB area in %s",
                     std_unit(self.mmap_size, unit=1024), mmap_filename)
예제 #14
0
 def parse_client_caps(self, c: typedict):
     self.uuid = c.strget("uuid")
     self.session_id = c.strget("session-id")
     self.machine_id = c.strget("machine_id")
     self.hostname = c.strget("hostname")
     self.username = c.strget("username")
     self.name = c.strget("name")
     self.argv = c.strtupleget("argv")
     self.sharing = c.boolget("share")
     self.client_type = c.strget("client_type", "PyGTK")
     self.client_platform = c.strget("platform")
     self.client_machine = c.strget("platform.machine")
     self.client_processor = c.strget("platform.processor")
     self.client_release = c.strget("platform.sysrelease")
     self.client_linux_distribution = c.strtupleget(
         "platform.linux_distribution")
     self.client_version = c.strget("version")
     self.client_revision = c.strget("build.revision")
     self.client_bits = c.intget("python.bits")
     self.client_proxy = c.boolget("proxy")
     self.client_wm_name = c.strget("wm_name")
     self.client_session_type = c.strget("session-type")
     self.client_session_type_full = c.strget("session-type.full", "")
     self.client_setting_change = c.boolget("setting-change")
     self.client_opengl = typedict(c.dictget("opengl") or {})
     self.proxy_hostname = c.strget("proxy.hostname")
     self.proxy_platform = c.strget("proxy.platform")
     self.proxy_release = c.strget("proxy.platform.sysrelease")
     self.proxy_version = c.strget("proxy.version")
     self.proxy_version = c.strget("proxy.build.version",
                                   self.proxy_version)
     log("client uuid %s", self.uuid)
예제 #15
0
    def parse_server_capabilities(self, c: typedict) -> bool:
        for cb in CLIENT_BASES:
            if not cb.parse_server_capabilities(self, c):
                log.info("failed to parse server capabilities in %s", cb)
                return False
        self.server_session_name = strtobytes(c.rawget("session_name",
                                                       b"")).decode("utf-8")
        set_name("Xpra", self.session_name or self.server_session_name
                 or "Xpra")
        self.server_platform = c.strget("platform")
        self.server_sharing = c.boolget("sharing")
        self.server_sharing_toggle = c.boolget("sharing-toggle")
        self.server_lock = c.boolget("lock")
        self.server_lock_toggle = c.boolget("lock-toggle")
        self.server_keyboard = c.boolget("keyboard", True)
        self.server_pointer = c.boolget("pointer", True)
        self.server_start_new_commands = c.boolget("start-new-commands")
        if self.server_start_new_commands:
            self.server_xdg_menu = c.dictget("xdg-menu", None)
        if self.start_new_commands or self.start_child_new_commands:
            if self.server_start_new_commands:
                self.after_handshake(self.send_start_new_commands)
            else:
                log.warn("Warning: cannot start new commands")
                log.warn(" the feature is currently disabled on the server")
        self.server_commands_info = c.boolget("server-commands-info")
        self.server_commands_signals = c.strtupleget("server-commands-signals")
        self.server_readonly = c.boolget("readonly")
        if self.server_readonly and not self.readonly:
            log.info("server is read only")
            self.readonly = True
        if not self.server_keyboard and self.keyboard_helper:
            #swallow packets:
            def nosend(*_args):
                pass

            self.keyboard_helper.send = nosend

        i = platform_name(
            self._remote_platform,
            c.strtupleget("platform.linux_distribution")
            or c.strget("platform.release", ""))
        r = self._remote_version
        if self._remote_revision:
            r += "-r%s" % self._remote_revision
        mode = c.strget("server.mode", "server")
        bits = c.intget("python.bits", 32)
        log.info("Xpra %s server version %s %i-bit", mode, std(r), bits)
        if i:
            log.info(" running on %s", std(i))
        if c.boolget("desktop") or c.boolget("shadow"):
            v = c.intpair("actual_desktop_size")
            if v:
                w, h = v
                ss = c.tupleget("screen_sizes")
                if ss:
                    log.info(" remote desktop size is %sx%s with %s screen%s:",
                             w, h, len(ss), engs(ss))
                    log_screen_sizes(w, h, ss)
                else:
                    log.info(" remote desktop size is %sx%s", w, h)
        if c.boolget("proxy"):
            proxy_hostname = c.strget("proxy.hostname")
            proxy_platform = c.strget("proxy.platform")
            proxy_release = c.strget("proxy.platform.release")
            proxy_version = c.strget("proxy.version")
            proxy_version = c.strget("proxy.build.version", proxy_version)
            proxy_distro = c.strget("proxy.linux_distribution")
            msg = "via: %s proxy version %s" % (platform_name(
                proxy_platform, proxy_distro
                or proxy_release), std(proxy_version or "unknown"))
            if proxy_hostname:
                msg += " on '%s'" % std(proxy_hostname)
            log.info(msg)
        return True
예제 #16
0
def caps_to_revision(caps: typedict) -> str:
    revision = caps.strget("revision")
    local_modifications = caps.intget("local_modifications")
    commit = caps.strget("commit")
    branch = caps.strget("branch")
    return make_revision_str(revision, local_modifications, branch, commit)
예제 #17
0
def caps_to_version(caps: typedict) -> str:
    return caps.strget("version") + "-" + caps_to_revision(caps)
예제 #18
0
 def parse_server_capabilities(self, c : typedict) -> bool:
     self._remote_machine_id = c.strget("machine_id")
     self._remote_uuid = c.strget("uuid")
     self._remote_version = c.strget("build.version", c.strget("version"))
     self._remote_revision = c.strget("build.revision", c.strget("revision"))
     mods = c.rawget("build.local_modifications")
     if mods and str(mods).find("dfsg")>=0:
         get_util_logger().warn("Warning: the xpra server is running a buggy Debian version")
         get_util_logger().warn(" those are usually out of date and unstable")
     else:
         self._remote_modifications = c.intget("build.local_modifications", 0)
     self._remote_build_date = c.strget("build.date")
     self._remote_build_time = c.strget("build.time")
     self._remote_hostname = c.strget("hostname")
     self._remote_display = c.strget("display")
     self._remote_platform = c.strget("platform")
     self._remote_platform_release = c.strget("platform.release")
     self._remote_platform_platform = c.strget("platform.platform")
     self._remote_python_version = c.strget("python.version")
     self._remote_subcommands = c.strtupleget("subcommands")
     for x in ("glib", "gobject", "gtk", "gdk", "cairo", "pango", "sound.gst", "sound.pygst"):
         v = c.rawget("%s.version" % x, None)
         if v is not None:
             self._remote_lib_versions[x] = v
     #linux distribution is a tuple of different types, ie: ('Linux Fedora' , 20, 'Heisenbug')
     pld = c.tupleget("platform.linux_distribution")
     if pld and len(pld)==3:
         def san(v):
             if isinstance(v, int):
                 return v
             return bytestostr(v)
         self._remote_platform_linux_distribution = [san(x) for x in pld]
     verr = version_compat_check(self._remote_version)
     if verr is not None:
         self.warn_and_quit(EXIT_INCOMPATIBLE_VERSION,
                            "incompatible remote version '%s': %s" % (self._remote_version, verr))
         return False
     return True