Ejemplo n.º 1
0
class XRootPropWatcher(gobject.GObject):
    __gsignals__ = {
        "root-prop-changed": n_arg_signal(2),
        "wimpiggy-property-notify-event": n_arg_signal(1),
    }

    def __init__(self, props):
        gobject.GObject.__init__(self)
        self._props = props
        self._root = gtk.gdk.get_default_root_window()
        add_event_receiver(self._root, self)

    def do_wimpiggy_property_notify_event(self, event):
        if event.atom in self._props:
            self._notify(event.atom)

    def _notify(self, prop):
        v = prop_get(gtk.gdk.get_default_root_window(),
                     prop,
                     "latin1",
                     ignore_errors=True)
        self.emit("root-prop-changed", prop, v)

    def notify_all(self):
        for prop in self._props:
            self._notify(prop)
Ejemplo n.º 2
0
class SoundSource(SoundPipeline):

    __gsignals__ = {
        "new-buffer": n_arg_signal(2),
    }

    def __init__(self,
                 src_type=DEFAULT_SRC,
                 src_options={},
                 codec=MP3,
                 encoder_options={}):
        assert src_type in SOURCES
        encoder, fmt = get_encoder_formatter(codec)
        SoundPipeline.__init__(self, codec)
        self.src_type = src_type
        source_str = plugin_str(src_type, src_options)
        encoder_str = plugin_str(encoder, encoder_options)
        pipeline_els = [source_str]
        if AUDIOCONVERT:
            pipeline_els += ["audioconvert"]
        if AUDIORESAMPLE:
            pipeline_els += [
                "audioresample", "audio/x-raw-int,rate=44100,channels=2"
            ]
        pipeline_els += [encoder_str, fmt, "appsink name=sink"]
        self.setup_pipeline_and_bus(pipeline_els)
        self.sink = self.pipeline.get_by_name("sink")
        self.sink.set_property("emit-signals", True)
        self.sink.set_property("max-buffers", 10)
        self.sink.set_property("drop", False)
        self.sink.set_property("sync", True)
        self.sink.set_property("qos", False)
        self.sink.connect("new-buffer", self.on_new_buffer)
        self.sink.connect("new-preroll", self.on_new_preroll)

    def cleanup(self):
        SoundPipeline.cleanup(self)
        self.src_type = ""
        self.sink = None

    def on_new_preroll(self, appsink):
        buf = appsink.emit('pull-preroll')
        debug('new preroll: %s bytes', len(buf))
        self.emit_buffer(buf)

    def on_new_buffer(self, bus):
        buf = self.sink.emit("pull-buffer")
        self.emit_buffer(buf)

    def emit_buffer(self, buf):
        """ convert pygst structure into something more generic for the wire """
        #none of the metadata is really needed at present, but it may be in the future:
        #metadata = {"caps"      : buf.get_caps().to_string(),
        #            "size"      : buf.size,
        #            "timestamp" : buf.timestamp,
        #            "duration"  : buf.duration,
        #            "offset"    : buf.offset,
        #            "offset_end": buf.offset_end}
        metadata = {}
        self.emit("new-buffer", buf.data, metadata)
Ejemplo n.º 3
0
class XpraClient(XpraClientBase):
    __gsignals__ = {
        "clipboard-toggled": n_arg_signal(0),
        "keyboard-sync-toggled": n_arg_signal(0),
    }

    def __init__(self, conn, opts):
        XpraClientBase.__init__(self, opts)
        self.start_time = time.time()
        self._window_to_id = {}
        self._id_to_window = {}
        self.title = opts.title
        self.readonly = opts.readonly
        self.session_name = opts.session_name
        self.compression_level = opts.compression_level
        self.auto_refresh_delay = opts.auto_refresh_delay
        self.max_bandwidth = opts.max_bandwidth
        if self.max_bandwidth > 0.0 and self.jpegquality == 0:
            """ jpegquality was not set, use a better start value """
            self.jpegquality = 50
        self.dpi = int(opts.dpi)

        #statistics:
        self.server_start_time = -1
        self.server_platform = ""
        self.server_actual_desktop_size = None
        self.server_randr = False
        self.pixel_counter = maxdeque(maxlen=100)
        self.server_latency = maxdeque(maxlen=100)
        self.server_load = None
        self.client_latency = maxdeque(maxlen=100)
        self.last_ping_echoed_time = 0

        #features:
        self.toggle_cursors_bell_notify = False
        self.toggle_keyboard_sync = False
        self.window_configure = False
        self._client_extras = ClientExtras(self, opts)
        self.client_supports_notifications = opts.notifications and self._client_extras.can_notify(
        )
        self.client_supports_clipboard = opts.clipboard and self._client_extras.supports_clipboard(
        ) and not self.readonly
        self.client_supports_cursors = opts.cursors
        self.client_supports_bell = opts.bell
        self.notifications_enabled = self.client_supports_notifications
        self.clipboard_enabled = self.client_supports_clipboard
        self.cursors_enabled = self.client_supports_cursors
        self.bell_enabled = self.client_supports_bell

        #mmap:
        self.mmap_enabled = False
        self.mmap = None
        self.mmap_token = None
        self.mmap_file = None
        self.mmap_size = 0
        self.supports_mmap = opts.mmap and (
            "rgb24" in ENCODINGS) and self._client_extras.supports_mmap()
        if self.supports_mmap:
            self.init_mmap(opts.mmap_group, conn.filename)

        self.init_packet_handlers()
        self.ready(conn)

        #keyboard:
        self.keyboard_sync = opts.keyboard_sync
        self.key_repeat_delay = -1
        self.key_repeat_interval = -1
        self.keys_pressed = {}
        self._remote_version = None
        self._keymap_changing = False
        try:
            self._keymap = gdk.keymap_get_default()
        except:
            self._keymap = None
        self._do_keys_changed()
        self.key_shortcuts = self.parse_shortcuts(opts.key_shortcuts)
        self.send_hello()

        if self._keymap:
            self._keymap.connect("keys-changed", self._keys_changed)

        self._focused = None

        def compute_receive_bandwidth(delay):
            bytecount = self._protocol.input_bytecount
            bw = (
                (bytecount - self.last_input_bytecount) / 1024) * 1000 / delay
            self.last_input_bytecount = bytecount
            log.debug("Bandwidth is ", bw, "kB/s, max ", self.max_bandwidth,
                      "kB/s")
            q = self.jpegquality
            if bw > self.max_bandwidth:
                q -= 10
            elif bw < self.max_bandwidth:
                q += 5
            q = max(10, min(95, q))
            self.send_jpeg_quality(q)
            return True

        if (self.max_bandwidth):
            self.last_input_bytecount = 0
            gobject.timeout_add(2000, compute_receive_bandwidth, 2000)
        if opts.send_pings:
            gobject.timeout_add(1000, self.send_ping)
        else:
            gobject.timeout_add(20 * 1000, self.send_ping)

    def init_mmap(self, mmap_group, socket_filename):
        log("init_mmap(%s, %s)", mmap_group, socket_filename)
        try:
            import mmap
            import tempfile
            import uuid
            from stat import S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP
            mmap_dir = os.getenv("TMPDIR", "/tmp")
            if not os.path.exists(mmap_dir):
                raise Exception("TMPDIR %s does not exist!" % mmap_dir)
            #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures
            #that the file is readable and writable only by the creating user ID
            temp = tempfile.NamedTemporaryFile(prefix="xpra.",
                                               suffix=".mmap",
                                               dir=mmap_dir)
            #keep a reference to it so it does not disappear!
            self._mmap_temp_file = temp
            self.mmap_file = temp.name
            fd = temp.file.fileno()
            #set the group permissions and gid if the mmap-group option is specified
            if mmap_group and type(socket_filename) == str and os.path.exists(
                    socket_filename):
                s = os.stat(socket_filename)
                os.fchown(fd, -1, s.st_gid)
                os.fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
            self.mmap_size = max(4096,
                                 mmap.PAGESIZE) * 32 * 1024  #generally 128MB
            log("using mmap file %s, fd=%s, size=%s", self.mmap_file, fd,
                self.mmap_size)
            os.lseek(fd, self.mmap_size - 1, os.SEEK_SET)
            assert os.write(fd, '\x00')
            os.lseek(fd, 0, os.SEEK_SET)
            self.mmap = mmap.mmap(fd, length=self.mmap_size)
            #write the 16 byte token one byte at a time - no endianness
            self.mmap_token = uuid.uuid4().int
            log.debug("mmap_token=%s", self.mmap_token)
            v = self.mmap_token
            for i in range(0, 16):
                poke = ctypes.c_ubyte.from_buffer(self.mmap, 512 + i)
                poke.value = v % 256
                v = v >> 8
            assert v == 0
        except Exception, e:
            log.error("failed to setup mmap: %s", e)
            self.supports_mmap = False
            self.clean_mmap()
            self.mmap = None
            self.mmap_file = None
            self.mmap_size = 0
Ejemplo n.º 4
0
class ClipboardProxy(gtk.Invisible):
    __gsignals__ = {
        # arguments: (selection, target)
        "get-clipboard-from-remote": (
            gobject.SIGNAL_RUN_LAST,
            gobject.TYPE_PYOBJECT,
            (gobject.TYPE_PYOBJECT, ) * 2,
        ),
        # arguments: (selection,)
        "send-clipboard-token":
        n_arg_signal(1),
    }

    def __init__(self, selection):
        gtk.Invisible.__init__(self)
        self.add_events(gtk.gdk.PROPERTY_CHANGE_MASK)
        self._selection = selection
        self._clipboard = gtk.Clipboard(selection=selection)
        self._have_token = False

    def do_selection_request_event(self, event):
        log.debug("do_selection_request_event(%s)", event)
        try:
            from wimpiggy.prop import prop_get
            from wimpiggy.error import trap
        except ImportError:
            gtk.Invisible.do_selection_request_event(self, event)
            return

        # Black magic: the superclass default handler for this signal
        # implements all the hards parts of selection handling, occasionally
        # calling back to the do_selection_get handler (below) to actually get
        # the data to be sent.  However, it only does this for targets that
        # have been registered ahead of time; other targets fall through to a
        # default implementation that cannot be overridden.  So, we swoop in
        # ahead of time and add whatever target was requested to the list of
        # targets we want to handle!
        #
        # Special cases (magic targets defined by ICCCM):
        #   TIMESTAMP: the remote side has a different timeline than us, so
        #     sending TIMESTAMPS across the wire doesn't make any sense. We
        #     ignore TIMESTAMP requests, and let them fall through to GTK+'s
        #     default handler.
        #   TARGET: GTK+ has default handling for this, but we don't want to
        #     use it. Fortunately, if we tell GTK+ that we can handle TARGET
        #     requests, then it will pass them on to us rather than fall
        #     through to the default handler.
        #   MULTIPLE: Ugh. To handle this properly, we need to go out
        #     ourselves and fetch the magic property off the requesting window
        #     (with proper error trapping and all), and interpret its
        #     contents. Probably doable (FIXME), just a pain.
        #
        # Another special case is that if an app requests the contents of a
        # clipboard that it currently owns, then GTK+ will short-circuit the
        # normal logic and request the contents directly (i.e. it calls
        # gtk_selection_invoke_handler) -- without giving us a chance to
        # assert that we can handle the requested sort of target. Fortunately,
        # Xpra never needs to request the clipboard when it owns it, so that's
        # okay.
        assert str(event.selection) == self._selection
        target = str(event.target)
        if target == "TIMESTAMP":
            pass
        elif target == "MULTIPLE":

            def get_targets(targets):
                atoms = prop_get(event.window, event.property,
                                 ["multiple-conversion"])
                log("MULTIPLE clipboard atoms: %r", atoms)
                targets += atoms[::2]

            targets = []
            trap.swallow(get_targets, targets)
            log("MULTIPLE clipboard targets: %r", targets)
            for target in targets:
                self.selection_add_target(self._selection, target, 0)
        else:
            self.selection_add_target(self._selection, target, 0)
        gtk.Invisible.do_selection_request_event(self, event)

    # This function is called by GTK+ when we own the clipboard and a local
    # app is requesting its contents:
    def do_selection_get(self, selection_data, info, time):
        # Either call selection_data.set() or don't, and then return.
        # In practice, send a call across the wire, then block in a recursive
        # main loop.
        log.debug("do_selection_get(%s,%s,%s)", selection_data, info, time)
        assert self._selection == str(selection_data.selection)
        target = str(selection_data.target)
        result = self.emit("get-clipboard-from-remote", self._selection,
                           target)
        if result is not None and result["type"] is not None:
            log.debug(
                "do_selection_get(%s,%s,%s) calling selection_data.set(%s,%s,%s)",
                selection_data, info, time, result["type"], result["format"],
                len(result["data"]))
            selection_data.set(result["type"], result["format"],
                               result["data"])
        else:
            log("remote selection fetch timed out")

    def do_selection_clear_event(self, event):
        # Someone else on our side has the selection
        log.debug("do_selection_clear_event(%s) selection=%s", event,
                  self._selection)
        self._have_token = False

        # Emit a signal -> send a note to the other side saying "hey its
        # ours now"
        # Send off the anti-token.
        self.emit("send-clipboard-token", self._selection)
        gtk.Invisible.do_selection_clear_event(self, event)

    def got_token(self):
        # We got the anti-token.
        log.debug("got token")
        self._have_token = True
        if not self.selection_owner_set(self._selection):
            # I don't know how this can actually fail, given that we pass
            # CurrentTime, but just in case:
            log.warn("Failed to acquire local clipboard %s; " %
                     (self._selection, ) +
                     "will not be able to pass local apps " +
                     "contents of remote clipboard")

    # This function is called by the xpra core when the peer has requested the
    # contents of this clipboard:
    def get_contents(self, target, cb):
        log.debug("get_contents(%s,%s)", target, cb)
        if self._have_token:
            log.warn("Our peer requested the contents of the clipboard, but " +
                     "*I* thought *they* had it... weird.")
            cb(None, None, None)

        def unpack(clipboard, selection_data, data):
            if selection_data is None:
                cb(None, None, None)
            else:
                cb(str(selection_data.type), selection_data.format,
                   selection_data.data)

        self._clipboard.request_contents(target, unpack)
Ejemplo n.º 5
0
class XpraClientBase(gobject.GObject):
    """Base class for Xpra clients.
        Provides the glue code for:
        * sending packets via Protocol
        * handling packets received via _process_packet
    """

    __gsignals__ = {
        "handshake-complete": n_arg_signal(0),
        "received-gibberish": n_arg_signal(1),
        }

    def __init__(self, opts):
        gobject.GObject.__init__(self)
        self.exit_code = None
        self.password_file = opts.password_file
        self.encoding = opts.encoding
        self.jpegquality = opts.jpegquality
        self._protocol = None
        self.server_capabilities = {}
        self.init_packet_handlers()

    def ready(self, conn):
        log.debug("ready(%s)", conn)
        self._protocol = Protocol(conn, self.process_packet)
        ClientSource(self._protocol)
        self._protocol.start()

    def init_packet_handlers(self):
        self._packet_handlers = {
            "challenge": self._process_challenge,
            "disconnect": self._process_disconnect,
            "hello": self._process_hello,
            "set_deflate": self._process_set_deflate,
            Protocol.CONNECTION_LOST: self._process_connection_lost,
            Protocol.GIBBERISH: self._process_gibberish,
            }

    def send_hello(self, challenge_response=None):
        hello = self.make_hello(challenge_response)
        log.debug("send_hello(%s) packet=%s", challenge_response, hello)
        self.send(["hello", hello])

    def make_hello(self, challenge_response=None):
        capabilities = {}
        add_version_info(capabilities)
        if challenge_response:
            capabilities["challenge_response"] = challenge_response
        if self.encoding:
            capabilities["encoding"] = self.encoding
        capabilities["encodings"] = ENCODINGS
        if self.jpegquality:
            capabilities["jpeg"] = self.jpegquality
        capabilities["platform"] = sys.platform
        capabilities["raw_packets"] = True
        capabilities["chunked_compression"] = True
        capabilities["rencode"] = has_rencode
        capabilities["server-window-resize"] = True
        capabilities["randr_notify"] = False    #only client.py cares about this
        return capabilities

    def send(self, packet):
        if self._protocol and self._protocol.source:
            self._protocol.source.queue_ordinary_packet(packet)

    def send_now(self, packet):
        if self._protocol and self._protocol.source:
            self._protocol.source.queue_priority_packet(packet)

    def cleanup(self):
        if self._protocol:
            self._protocol.close()
            self._protocol = None

    def run(self):
        raise Exception("override me!")

    def quit(self, exit_code=0):
        if self.exit_code is None:
            self.exit_code = exit_code
        raise Exception("override me!")

    def _process_disconnect(self, packet):
        log.error("server requested disconnect: %s", packet[1:])
        self.quit(0)

    def _process_connection_lost(self, packet):
        log.error("Connection lost")
        self.quit(1)

    def _process_challenge(self, packet):
        if not self.password_file:
            log.error("password is required by the server")
            self.quit(2)
            return
        import hmac
        try:
            passwordFile = open(self.password_file, "rU")
            password = passwordFile.read()
            passwordFile.close()
            while password.endswith("\n") or password.endswith("\r"):
                password = password[:-1]
        except IOError, e:
            log.error("failed to open password file %s: %s", self.password_file, e)
            self.quit(3)
            return
        salt = packet[1]
        challenge_response = hmac.HMAC(password, salt)
        self.send_hello(challenge_response.hexdigest())
Ejemplo n.º 6
0
class XpraClient(gobject.GObject):
    __gsignals__ = {
        "handshake-complete": n_arg_signal(0),
        "received-gibberish": n_arg_signal(1),
    }

    def __init__(self, conn, compression_level):
        gobject.GObject.__init__(self)
        self._window_to_id = {}
        self._id_to_window = {}

        self._protocol = Protocol(conn, self.process_packet)
        ClientSource(self._protocol)
        capabilities_request = dict(default_capabilities)
        if compression_level:
            capabilities_request["deflate"] = compression_level
        root_w, root_h = gtk.gdk.get_default_root_window().get_size()
        capabilities_request["desktop_size"] = [root_w, root_h]
        self.send(["hello", capabilities_request])

        self._keymap = gtk.gdk.keymap_get_default()
        self._keymap.connect("keys-changed", self._keys_changed)
        self._keys_changed()

        self._xsettings_watcher = None
        self._root_props_watcher = None

        # FIXME: these should perhaps be merged.
        self._clipboard_helper = ClipboardProtocolHelper(self.send)
        self._client_extras = ClientExtras(self.send)

        self._focused = None

    def run(self):
        gtk_main_quit_on_fatal_exceptions_enable()
        gtk.main()

    def _keys_changed(self, *args):
        self._modifier_map = grok_modifier_map(gtk.gdk.display_get_default())

    def update_focus(self, id, gotit):
        if gotit and self._focused is not id:
            self.send(["focus", id])
            self._focused = id
        if not gotit and self._focused is id:
            self.send(["focus", 0])
            self._focused = None

    def mask_to_names(self, mask):
        return mask_to_names(mask, self._modifier_map)

    def send(self, packet):
        self._protocol.source.queue_ordinary_packet(packet)

    def send_positional(self, packet):
        self._protocol.source.queue_positional_packet(packet)

    def send_mouse_position(self, packet):
        self._protocol.source.queue_mouse_position_packet(packet)

    def _process_hello(self, packet):
        (_, capabilities) = packet
        if "deflate" in capabilities:
            self._protocol.enable_deflate(capabilities["deflate"])
        if capabilities.get("__prerelease_version") != xpra.__version__:
            log.error("sorry, I only know how to talk to v%s servers",
                      xpra.__version__)
            gtk.main_quit()
            return
        if "desktop_size" in capabilities:
            avail_w, avail_h = capabilities["desktop_size"]
            root_w, root_h = gtk.gdk.get_default_root_window().get_size()
            if (avail_w, avail_h) < (root_w, root_h):
                log.warn("Server's virtual screen is too small -- "
                         "(server: %sx%s vs. client: %sx%s)\n"
                         "You may see strange behavior.\n"
                         "Please complain to "
                         "*****@*****.**" %
                         (avail_w, avail_h, root_w, root_h))
        self._clipboard_helper.send_all_tokens()
        self._client_extras.handshake_complete(capabilities)
        self.emit("handshake-complete")

    def _process_new_common(self, packet, override_redirect):
        (_, id, x, y, w, h, metadata) = packet
        window = ClientWindow(self, id, x, y, w, h, metadata,
                              override_redirect)
        self._id_to_window[id] = window
        self._window_to_id[window] = id
        window.show_all()

    def _process_new_window(self, packet):
        self._process_new_common(packet, False)

    def _process_new_override_redirect(self, packet):
        self._process_new_common(packet, True)

    def _process_draw(self, packet):
        (_, id, x, y, width, height, coding, data) = packet
        window = self._id_to_window[id]
        assert coding == "rgb24"
        window.draw(x, y, width, height, data)

    def _process_window_metadata(self, packet):
        (_, id, metadata) = packet
        window = self._id_to_window[id]
        window.update_metadata(metadata)

    def _process_configure_override_redirect(self, packet):
        (_, id, x, y, w, h) = packet
        window = self._id_to_window[id]
        window.move_resize(x, y, w, h)

    def _process_lost_window(self, packet):
        (_, id) = packet
        window = self._id_to_window[id]
        del self._id_to_window[id]
        del self._window_to_id[window]
        window.destroy()

    def _process_connection_lost(self, packet):
        log.error("Connection lost")
        gtk_main_quit_really()

    def _process_gibberish(self, packet):
        [_, data] = packet
        self.emit("received-gibberish", data)

    _packet_handlers = {
        "hello":
        _process_hello,
        "new-window":
        _process_new_window,
        "new-override-redirect":
        _process_new_override_redirect,
        "draw":
        _process_draw,
        "window-metadata":
        _process_window_metadata,
        "configure-override-redirect":
        _process_configure_override_redirect,
        "lost-window":
        _process_lost_window,
        # "clipboard-*" packets are handled by a special case below.
        Protocol.CONNECTION_LOST:
        _process_connection_lost,
        Protocol.GIBBERISH:
        _process_gibberish,
    }

    def process_packet(self, proto, packet):
        packet_type = packet[0]
        if (isinstance(packet_type, str)
                and packet_type.startswith("clipboard-")):
            self._clipboard_helper.process_clipboard_packet(packet)
        else:
            self._packet_handlers[packet_type](self, packet)
Ejemplo n.º 7
0
class XpraClientBase(gobject.GObject):
    """Base class for Xpra clients.
        Provides the glue code for:
        * sending packets via Protocol
        * handling packets received via _process_packet
    """

    __gsignals__ = {
        "handshake-complete": n_arg_signal(0),
        "received-gibberish": n_arg_signal(1),
        }

    def __init__(self, opts):
        gobject.GObject.__init__(self)
        self.password_file = opts.password_file
        self.encoding = opts.encoding
        self.jpegquality = opts.jpegquality
        self._protocol = None
        self.init_packet_handlers()

    def ready(self, conn):
        log.debug("ready(%s)", conn)
        self._protocol = Protocol(conn, self.process_packet)
        ClientSource(self._protocol)

    def init_packet_handlers(self):
        self._packet_handlers = {
            "challenge": self._process_challenge,
            "disconnect": self._process_disconnect,
            "hello": self._process_hello,
            "set_deflate": self._process_set_deflate,
            Protocol.CONNECTION_LOST: self._process_connection_lost,
            Protocol.GIBBERISH: self._process_gibberish,
            }

    def send_hello(self, challenge_response=None):
        hello = self.make_hello(challenge_response)
        log.debug("send_hello(%s) packet=%s", challenge_response, hello)
        self.send(["hello", hello])

    def make_hello(self, challenge_response=None):
        capabilities = {"version": xpra.__version__}
        if challenge_response:
            capabilities["challenge_response"] = challenge_response
        if self.encoding:
            capabilities["encoding"] = self.encoding
        capabilities["encodings"] = ENCODINGS
        if self.jpegquality:
            capabilities["jpeg"] = self.jpegquality
        capabilities["packet_size"] = True
        #will be removed (only for compatibility with old versions):
        capabilities["dynamic_compression"] = True
        capabilities["__prerelease_version"] = xpra.__version__
        return capabilities

    def send(self, packet):
        self._protocol.source.queue_ordinary_packet(packet)

    def send_now(self, packet):
        self._protocol.source.queue_priority_packet(packet)

    def cleanup(self):
        if self._protocol:
            self._protocol.close()
            self._protocol = None

    def run(self):
        raise Exception("override me!")

    def quit(self, *args):
        raise Exception("override me!")

    def _process_disconnect(self, packet):
        log.error("server requested disconnect: %s", packet[1:])
        self.quit()
        return

    def _process_challenge(self, packet):
        if not self.password_file:
            log.error("password is required by the server")
            self.quit()
            return
        import hmac
        try:
            passwordFile = open(self.password_file, "rU")
            password = passwordFile.read()
        except IOError, e:
            log.error("failed to open password file %s: %s", self.password_file, e)
            self.quit()
            return
        salt = packet[1]
        challenge_response = hmac.HMAC(password, salt)
        self.send_hello(challenge_response.hexdigest())
Ejemplo n.º 8
0
class XpraClient(XpraClientBase):
    __gsignals__ = {
        "clipboard-toggled": n_arg_signal(0),
        }

    def __init__(self, conn, opts):
        XpraClientBase.__init__(self, opts)
        self.start_time = time.time()
        self._window_to_id = {}
        self._id_to_window = {}
        title = opts.title
        if opts.title_suffix is not None:
            title = "@title@ %s" % opts.title_suffix
        self.title = title
        self.readonly = opts.readonly
        self.session_name = opts.session_name
        self.compression_level = opts.compression_level
        self.auto_refresh_delay = opts.auto_refresh_delay
        self.max_bandwidth = opts.max_bandwidth
        if self.max_bandwidth>0.0 and self.jpegquality==0:
            """ jpegquality was not set, use a better start value """
            self.jpegquality = 50

        self.server_capabilities = {}

        self.can_ping = False
        self.mmap_enabled = False
        self.server_start_time = -1
        self.server_platform = ""
        self.server_actual_desktop_size = None
        self.server_desktop_size = None
        self.server_randr = False
        self.pixel_counter = deque(maxlen=100)
        self.server_latency = deque(maxlen=100)
        self.server_load = None
        self.client_latency = deque(maxlen=100)
        self.bell_enabled = True
        self.notifications_enabled = True
        self.send_damage_sequence = False
        self.clipboard_enabled = False
        self.mmap = None
        self.mmap_token = None
        self.mmap_file = None
        self.mmap_size = 0

        self._client_extras = ClientExtras(self, opts)
        self.clipboard_enabled = not self.readonly and opts.clipboard and self._client_extras.supports_clipboard()
        self.supports_mmap = opts.mmap and self._client_extras.supports_mmap()
        if self.supports_mmap:
            try:
                import mmap
                import tempfile
                import uuid
                import ctypes
                from stat import S_IRUSR,S_IWUSR
                mmap_dir = os.getenv("TMPDIR", "/tmp")
                if not os.path.exists(mmap_dir):
                    raise Exception("TMPDIR %s does not exist!" % mmap_dir)
                temp = tempfile.NamedTemporaryFile(prefix="xpra.", suffix=".mmap", dir=mmap_dir)
                #keep a reference to it so it does not disappear!
                self._mmap_temp_file = temp
                self.mmap_file = temp.name
                #ensure that the permissions are strict:
                os.chmod(self.mmap_file, S_IRUSR|S_IWUSR)
                self.mmap_size = max(4096, mmap.PAGESIZE)*32*1024   #generally 128MB
                fd = temp.file.fileno()
                log("using mmap file %s, fd=%s, size=%s", self.mmap_file, fd, self.mmap_size)
                os.lseek(fd, self.mmap_size-1, os.SEEK_SET)
                assert os.write(fd, '\x00')
                os.lseek(fd, 0, os.SEEK_SET)
                self.mmap = mmap.mmap(fd, length=self.mmap_size)
                #write the 16 byte token one byte at a time - no endianness
                self.mmap_token = uuid.uuid4().int
                log.debug("mmap_token=%s", self.mmap_token)
                v = self.mmap_token
                for i in range(0,16):
                    poke = ctypes.c_ubyte.from_buffer(self.mmap, 512+i)
                    poke.value = v % 256
                    v = v>>8
                assert v==0
            except Exception, e:
                log.error("failed to setup mmap: %s", e)
                self.supports_mmap = False
                self.clean_mmap()
                self.mmap = None
                self.mmap_file = None
                self.mmap_size = 0

        self.init_packet_handlers()
        self.ready(conn)

        self.keyboard_sync = opts.keyboard_sync
        self.key_repeat_modifiers = False
        self.key_repeat_delay = -1
        self.key_repeat_interval = -1
        self.keys_pressed = {}
        self.send_nuisance_modifiers = False
        self.keyboard_as_properties = False
        self._raw_keycodes_feature = False
        self._raw_keycodes_full = False
        self._focus_modifiers_feature = False
        self._remote_version = None
        self._keymap_changing = False
        self._keymap = gtk.gdk.keymap_get_default()
        self._do_keys_changed()
        self.key_shortcuts = self.parse_shortcuts(opts.key_shortcuts)
        self.send_hello()

        self._keymap.connect("keys-changed", self._keys_changed)
        self._xsettings_watcher = None
        self._root_props_watcher = None

        self._focused = None
        def compute_receive_bandwidth(delay):
            bw = (self._protocol._recv_counter / 1024) * 1000/ delay;
            self._protocol._recv_counter = 0;
            log.debug("Bandwidth is ", bw, "kB/s, max ", self.max_bandwidth, "kB/s")
            q = self.jpegquality
            if bw > self.max_bandwidth:
                q -= 10
            elif bw < self.max_bandwidth:
                q += 5
            q = max(10, min(95 ,q))
            self.send_jpeg_quality(q)
            return True
        if (self.max_bandwidth):
            gobject.timeout_add(2000, compute_receive_bandwidth, 2000);
Ejemplo n.º 9
0
class ClipboardProxy(gtk.Invisible):
    __gsignals__ = {
        # arguments: (selection, target)
        "get-clipboard-from-remote": (
            gobject.SIGNAL_RUN_LAST,
            gobject.TYPE_PYOBJECT,
            (gobject.TYPE_PYOBJECT, ) * 2,
        ),
        # arguments: (selection,)
        "send-clipboard-token":
        n_arg_signal(1),
    }

    def __init__(self, selection):
        gtk.Invisible.__init__(self)
        self.add_events(PROPERTY_CHANGE_MASK)
        self._selection = selection
        self._clipboard = gtk.Clipboard(selection=selection)
        self._have_token = False
        #clients that need a new token for every owner-change: (ie: win32)
        self._greedy_client = False
        #semaphore to block the sending of the token when we change the owner ourselves:
        self._block_owner_change = False
        self._clipboard.connect("owner-change", self.do_owner_changed)

    def set_greedy_client(self, greedy):
        debug("%s.set_greedy_client(%s)", self, greedy)
        self._greedy_client = greedy

    def __str__(self):
        return "ClipboardProxy(%s)" % self._selection

    def do_owner_changed(self, *args):
        debug("do_owner_changed(%s) greedy_client=%s, block_owner_change=%s",
              args, self._greedy_client, self._block_owner_change)
        if self._greedy_client and not self._block_owner_change:
            self._have_token = False
            self.emit("send-clipboard-token", self._selection)

    def do_selection_request_event(self, event):
        debug("do_selection_request_event(%s)", event)
        # Black magic: the superclass default handler for this signal
        # implements all the hards parts of selection handling, occasionally
        # calling back to the do_selection_get handler (below) to actually get
        # the data to be sent.  However, it only does this for targets that
        # have been registered ahead of time; other targets fall through to a
        # default implementation that cannot be overridden.  So, we swoop in
        # ahead of time and add whatever target was requested to the list of
        # targets we want to handle!
        #
        # Special cases (magic targets defined by ICCCM):
        #   TIMESTAMP: the remote side has a different timeline than us, so
        #     sending TIMESTAMPS across the wire doesn't make any sense. We
        #     ignore TIMESTAMP requests, and let them fall through to GTK+'s
        #     default handler.
        #   TARGET: GTK+ has default handling for this, but we don't want to
        #     use it. Fortunately, if we tell GTK+ that we can handle TARGET
        #     requests, then it will pass them on to us rather than fall
        #     through to the default handler.
        #   MULTIPLE: Ugh. To handle this properly, we need to go out
        #     ourselves and fetch the magic property off the requesting window
        #     (with proper error trapping and all), and interpret its
        #     contents. Probably doable (FIXME), just a pain.
        #
        # Another special case is that if an app requests the contents of a
        # clipboard that it currently owns, then GTK+ will short-circuit the
        # normal logic and request the contents directly (i.e. it calls
        # gtk_selection_invoke_handler) -- without giving us a chance to
        # assert that we can handle the requested sort of target. Fortunately,
        # Xpra never needs to request the clipboard when it owns it, so that's
        # okay.
        assert str(event.selection) == self._selection
        target = str(event.target)
        if target == "TIMESTAMP":
            pass
        elif target == "MULTIPLE":
            try:
                from wimpiggy.prop import prop_get
            except ImportError:
                debug(
                    "MULTIPLE for property '%s' not handled due to missing wimpiggy bindings",
                    event.property)
                gtk.Invisible.do_selection_request_event(self, event)
                return
            atoms = prop_get(event.window, event.property,
                             ["multiple-conversion"])
            debug("MULTIPLE clipboard atoms: %r", atoms)
            if atoms:
                targets = atoms[::2]
                for t in targets:
                    self.selection_add_target(self._selection, t, 0)
        else:
            debug("target for %s: %r", self._selection, target)
            self.selection_add_target(self._selection, target, 0)
        debug("do_selection_request_event(%s) target=%s, selection=%s", event,
              target, self._selection)
        gtk.Invisible.do_selection_request_event(self, event)

    # This function is called by GTK+ when we own the clipboard and a local
    # app is requesting its contents:
    def do_selection_get(self, selection_data, info, time):
        # Either call selection_data.set() or don't, and then return.
        # In practice, send a call across the wire, then block in a recursive
        # main loop.
        debug("do_selection_get(%s, %s, %s) selection=%s", selection_data,
              info, time, selection_data.selection)
        assert self._selection == str(selection_data.selection)
        target = str(selection_data.target)
        result = self.emit("get-clipboard-from-remote", self._selection,
                           target)
        if result is None or result["type"] is None:
            debug("remote selection fetch timed out or empty")
            return
        data = result["data"]
        dformat = result["format"]
        dtype = result["type"]
        debug(
            "do_selection_get(%s,%s,%s) calling selection_data.set(%s, %s, %s:%s)",
            selection_data, info, time, dtype, dformat, type(data),
            len(data or ""))
        selection_data.set(dtype, dformat, data)

    def do_selection_clear_event(self, event):
        # Someone else on our side has the selection
        debug("do_selection_clear_event(%s) selection=%s", event,
              self._selection)
        #if greedy_client is set, do_owner_changed will fire the token
        #so don't bother sending it now (same if we don't have it)
        send = ((self._greedy_client and not self._block_owner_change)
                or self._have_token)
        self._have_token = False

        # Emit a signal -> send a note to the other side saying "hey its
        # ours now"
        # Send off the anti-token.
        if send:
            self.emit("send-clipboard-token", self._selection)
        gtk.Invisible.do_selection_clear_event(self, event)

    def got_token(self, targets):
        # We got the anti-token.
        debug("got token, selection=%s, targets=%s", self._selection, targets)
        self._have_token = True
        if self._greedy_client:
            self._block_owner_change = True
        if not self.selection_owner_set(self._selection):
            # I don't know how this can actually fail, given that we pass
            # CurrentTime, but just in case:
            log.warn("Failed to acquire local clipboard %s; " %
                     (self._selection, ) +
                     "will not be able to pass local apps " +
                     "contents of remote clipboard")
        if self._block_owner_change:
            #re-enable the flag via idle_add so events like do_owner_changed
            #get a chance to run first.
            def remove_block(*args):
                self._block_owner_change = False

            gobject.idle_add(remove_block)

    # This function is called by the xpra core when the peer has requested the
    # contents of this clipboard:
    def get_contents(self, target, cb):
        debug("get_contents(%s,%s) selection=%s", target, cb, self._selection)
        if self._have_token:
            log.warn("Our peer requested the contents of the clipboard, but " +
                     "*I* thought *they* had it... weird.")
            cb(None, None, None)
            return
        if target == "TARGETS":
            #handle TARGETS using "request_targets"
            def got_targets(c, targets, *args):
                debug("got_targets(%s, %s, %s)", c, targets, args)
                cb("ATOM", 32, targets)

            self._clipboard.request_targets(got_targets)
            return

        def unpack(clipboard, selection_data, user_data):
            debug("unpack: %s", type(selection_data))
            if selection_data is None:
                cb(None, None, None)
                return
            debug("unpack(..) type=%s, format=%s, data=%s:%s",
                  selection_data.type, selection_data.format,
                  type(selection_data.data), len(selection_data.data or ""))
            cb(str(selection_data.type), selection_data.format,
               selection_data.data)

        self._clipboard.request_contents(target, unpack)
Ejemplo n.º 10
0
class XpraClientBase(gobject.GObject):
    """Base class for Xpra clients.
        Provides the glue code for:
        * sending packets via Protocol
        * handling packets received via _process_packet
    """

    __gsignals__ = {
        "handshake-complete": n_arg_signal(0),
        "first-ui-received": n_arg_signal(0),
        "received-gibberish": n_arg_signal(1),
    }

    def __init__(self, opts):
        gobject.GObject.__init__(self)
        self.exit_code = None
        self.compression_level = opts.compression_level
        self.password = None
        self.password_file = opts.password_file
        self.encoding = opts.encoding
        self.quality = opts.quality
        self._protocol = None
        self.server_capabilities = {}
        self._remote_version = None
        self._remote_revision = None
        self.init_packet_handlers()

    def ready(self, conn):
        log.debug("ready(%s)", conn)
        self._protocol = Protocol(conn, self.process_packet)
        self._protocol.set_compression_level(self.compression_level)
        ClientSource(self._protocol)
        self._protocol.start()

    def init_packet_handlers(self):
        self._packet_handlers = {}
        self._ui_packet_handlers = {
            "challenge": self._process_challenge,
            "disconnect": self._process_disconnect,
            "hello": self._process_hello,
            "set_deflate": self._process_set_deflate,
            Protocol.CONNECTION_LOST: self._process_connection_lost,
            Protocol.GIBBERISH: self._process_gibberish,
        }

    def send_hello(self, challenge_response=None):
        hello = self.make_hello(challenge_response)
        log.debug("send_hello(%s) packet=%s", challenge_response, hello)
        self.send(["hello", hello])

    def make_hello(self, challenge_response=None):
        capabilities = {}
        add_version_info(capabilities)
        if challenge_response:
            capabilities["challenge_response"] = challenge_response
        if self.encoding:
            capabilities["encoding"] = self.encoding
        capabilities["encodings"] = ENCODINGS
        if self.quality >= 0:
            capabilities["jpeg"] = self.quality
            capabilities["quality"] = self.quality
        capabilities["platform"] = sys.platform
        capabilities["client_type"] = "Python/Gobject"
        capabilities["raw_packets"] = True
        capabilities["chunked_compression"] = True
        capabilities["rencode"] = has_rencode
        capabilities["server-window-resize"] = True
        u = hashlib.sha512()
        u.update(str(get_machine_id()))
        if os.name == "posix":
            u.update("/")
            u.update(str(os.getuid()))
            u.update("/")
            u.update(str(os.getgid()))
        capabilities["uuid"] = u.hexdigest()
        capabilities["randr_notify"] = False  #only client.py cares about this
        capabilities["windows"] = False  #only client.py cares about this
        return capabilities

    def idle_send(self, packet):
        gobject.idle_add(self.send, packet)

    def send(self, packet):
        if self._protocol and self._protocol.source:
            self._protocol.source.queue_ordinary_packet(packet)

    def send_now(self, packet):
        if self._protocol and self._protocol.source:
            self._protocol.source.queue_priority_packet(packet)

    def cleanup(self):
        if self._protocol:
            self._protocol.close()
            self._protocol = None

    def run(self):
        raise Exception("override me!")

    def quit(self, exit_code=0):
        if self.exit_code is None:
            self.exit_code = exit_code
        raise Exception("override me!")

    def warn_and_quit(self, exit_code, warning):
        log.warn(warning)
        self.quit(exit_code)

    def _process_disconnect(self, packet):
        if len(packet) == 2:
            info = packet[1]
        else:
            info = packet[1:]
        self.warn_and_quit(EXIT_OK, "server requested disconnect: %s" % info)

    def _process_connection_lost(self, packet):
        self.warn_and_quit(EXIT_CONNECTION_LOST, "Connection lost")

    def _process_challenge(self, packet):
        if not self.password_file and not self.password:
            self.warn_and_quit(EXIT_PASSWORD_REQUIRED,
                               "password is required by the server")
            return
        if not self.password:
            self.load_password()
            log("password read from file %s is %s", self.password_file,
                self.password)
        if self.password:
            salt = packet[1]
            import hmac
            challenge_response = hmac.HMAC(self.password, salt)
            self.send_hello(challenge_response.hexdigest())

    def load_password(self):
        try:
            passwordFile = open(self.password_file, "rU")
            self.password = passwordFile.read()
            passwordFile.close()
            while self.password.endswith("\n") or self.password.endswith("\r"):
                self.password = self.password[:-1]
        except IOError, e:
            self.warn_and_quit(
                EXIT_PASSWORD_FILE_ERROR,
                "failed to open password file %s: %s" %
                (self.password_file, e))
Ejemplo n.º 11
0
class XpraClientBase(gobject.GObject):
    """Base class for Xpra clients.
        Provides the glue code for:
        * sending packets via Protocol
        * handling packets received via _process_packet
    """

    __gsignals__ = {
        "handshake-complete": n_arg_signal(0),
        "first-ui-received" : n_arg_signal(0),
        "received-gibberish": n_arg_signal(1),
        }

    def __init__(self, opts):
        gobject.GObject.__init__(self)
        self.exit_code = None
        self.compression_level = opts.compression_level
        self.password = None
        self.password_file = opts.password_file
        self.password_sent = False
        self.encoding = opts.encoding
        self.encryption = opts.encryption
        self.quality = opts.quality
        self.min_quality = opts.min_quality
        self.speed = opts.speed
        self.min_speed = opts.min_speed
        #protocol stuff:
        self._protocol = None
        self._priority_packets = []
        self._ordinary_packets = []
        self._mouse_position = None
        #server state and caps:
        self.server_capabilities = {}
        self._remote_version = None
        self._remote_revision = None
        self.make_uuid()
        self.init_packet_handlers()

    def ready(self, conn):
        log.debug("ready(%s)", conn)
        self._protocol = Protocol(conn, self.process_packet, self.next_packet)
        self._protocol.large_packets.append("keymap-changed")
        self._protocol.large_packets.append("server-settings")
        self._protocol.set_compression_level(self.compression_level)
        self._protocol.start()
        self.have_more = self._protocol.source_has_more

    def init_packet_handlers(self):
        self._packet_handlers = {
            "hello": self._process_hello,
            }
        self._ui_packet_handlers = {
            "challenge": self._process_challenge,
            "disconnect": self._process_disconnect,
            "set_deflate": self._process_set_deflate,
            Protocol.CONNECTION_LOST: self._process_connection_lost,
            Protocol.GIBBERISH: self._process_gibberish,
            }

    def send_hello(self, challenge_response=None):
        hello = self.make_hello(challenge_response)
        log.debug("send_hello(%s) packet=%s", challenge_response, hello)
        self.send("hello", hello)

    def make_hello(self, challenge_response=None):
        capabilities = {}
        add_version_info(capabilities)
        if challenge_response:
            assert self.password
            capabilities["challenge_response"] = challenge_response
        if self.encryption:
            assert self.encryption in ENCRYPTION_CIPHERS
            capabilities["cipher"] = self.encryption
            iv = uuid.uuid4().hex[:16]
            capabilities["cipher.iv"] = iv
            key_salt = uuid.uuid4().hex
            capabilities["cipher.key_salt"] = key_salt
            iterations = 1000
            capabilities["cipher.key_stretch_iterations"] = iterations
            self._protocol.set_cipher_in(self.encryption, iv, self.get_password(), key_salt, iterations)
        if self.encoding:
            capabilities["encoding"] = self.encoding
        capabilities["encodings"] = ENCODINGS
        if self.quality>0:
            capabilities["jpeg"] = self.quality
            capabilities["quality"] = self.quality
            capabilities["encoding.quality"] = self.quality
        if self.min_quality>0:
            capabilities["encoding.min-quality"] = self.min_quality
        if self.speed>=0:
            capabilities["speed"] = self.speed
            capabilities["encoding.speed"] = self.speed
        if self.min_speed>=0:
            capabilities["encoding.min-speed"] = self.min_speed
        capabilities["platform"] = sys.platform
        capabilities["client_type"] = "Python/Gobject"
        capabilities["raw_packets"] = True
        capabilities["chunked_compression"] = True
        capabilities["rencode"] = has_rencode
        capabilities["server-window-resize"] = True
        capabilities["hostname"] = socket.gethostname()
        capabilities["uuid"] = self.uuid
        capabilities["randr_notify"] = False    #only client.py cares about this
        capabilities["windows"] = False         #only client.py cares about this
        return capabilities

    def make_uuid(self):
        try:
            import hashlib
            u = hashlib.sha1()
        except:
            #try python2.4 variant:
            import sha
            u = sha.new()
        def uupdate(ustr):
            u.update(ustr.encode("utf-8"))
        uupdate(get_machine_id())
        if os.name=="posix":
            uupdate(u"/")
            uupdate(str(os.getuid()))
            uupdate(u"/")
            uupdate(str(os.getgid()))
        self.uuid = u.hexdigest()

    def send(self, *parts):
        self._ordinary_packets.append(parts)
        self.have_more()

    def send_now(self, *parts):
        self._priority_packets.append(parts)
        self.have_more()

    def send_positional(self, packet):
        self._ordinary_packets.append(packet)
        self._mouse_position = None
        self.have_more()

    def send_mouse_position(self, packet):
        self._mouse_position = packet
        self.have_more()

    def have_more(self):
        #this function is overridden in ready()
        p = self._protocol
        if p and p.source:
            p.source_has_more()

    def next_packet(self):
        if self._priority_packets:
            packet = self._priority_packets.pop(0)
        elif self._ordinary_packets:
            packet = self._ordinary_packets.pop(0)
        elif self._mouse_position is not None:
            packet = self._mouse_position
            self._mouse_position = None
        else:
            packet = None
        has_more = packet is not None and \
                (bool(self._priority_packets) or bool(self._ordinary_packets) \
                 or self._mouse_position is not None)
        return packet, None, None, has_more


    def cleanup(self):
        if self._protocol:
            self._protocol.close()
            self._protocol = None

    def run(self):
        raise Exception("override me!")

    def quit(self, exit_code=0):
        if self.exit_code is None:
            self.exit_code = exit_code
        raise Exception("override me!")

    def warn_and_quit(self, exit_code, warning):
        log.warn(warning)
        self.quit(exit_code)

    def _process_disconnect(self, packet):
        if len(packet)==2:
            info = packet[1]
        else:
            info = packet[1:]
        self.warn_and_quit(EXIT_OK, "server requested disconnect: %s" % info)

    def _process_connection_lost(self, packet):
        self.warn_and_quit(EXIT_CONNECTION_LOST, "Connection lost")

    def _process_challenge(self, packet):
        if not self.password_file and not self.password:
            self.warn_and_quit(EXIT_PASSWORD_REQUIRED, "password is required by the server")
            return
        if not self.password:
            self.load_password()
            assert self.password
        salt = packet[1]
        if self.encryption:
            assert len(packet)>=3, "challenge does not contain encryption details to use for the response"
            server_cipher = packet[2]
            self.set_server_encryption(server_cipher)
        import hmac
        challenge_response = hmac.HMAC(self.password, salt)
        password_hash = challenge_response.hexdigest()
        self.password_sent = True
        self.send_hello(password_hash)

    def set_server_encryption(self, props):
        cipher = props.get("cipher")
        cipher_iv = props.get("cipher.iv")
        key_salt = props.get("cipher.key_salt")
        iterations = props.get("cipher.key_stretch_iterations")
        if not cipher or not cipher_iv:
            self.warn_and_quit(EXIT_ENCRYPTION, "the server does not use or support encryption/password, cannot continue with %s cipher" % self.encryption)
            return False
        if cipher not in ENCRYPTION_CIPHERS:
            self.warn_and_quit(EXIT_ENCRYPTION, "unsupported server cipher: %s, allowed ciphers: %s" % (cipher, ", ".join(ENCRYPTION_CIPHERS)))
            return False
        self._protocol.set_cipher_out(cipher, cipher_iv, self.get_password(), key_salt, iterations)


    def get_password(self):
        if self.password is None:
            self.load_password()
        return self.password

    def load_password(self):
        try:
            passwordFile = open(self.password_file, "rU")
            self.password = passwordFile.read()
            passwordFile.close()
            while self.password.endswith("\n") or self.password.endswith("\r"):
                self.password = self.password[:-1]
        except IOError, e:
            self.warn_and_quit(EXIT_PASSWORD_FILE_ERROR, "failed to open password file %s: %s" % (self.password_file, e))
        log("password read from file %s is %s", self.password_file, self.password)