Skip to content

Commit

Permalink
#1761 move file-transfers and printing to a mixin
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@18563 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Feb 23, 2018
1 parent df04e38 commit 0993f20
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 122 deletions.
128 changes: 6 additions & 122 deletions src/xpra/server/source/client_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
mouselog = Logger("mouse")
cursorlog = Logger("cursor")
metalog = Logger("metadata")
printlog = Logger("printing")
filelog = Logger("file")
timeoutlog = Logger("timeout")
proxylog = Logger("proxy")
avsynclog = Logger("av-sync")
Expand All @@ -34,6 +32,7 @@
from xpra.server.source.source_stats import GlobalPerformanceStatistics
from xpra.server.source.audio_mixin import AudioMixin
from xpra.server.source.mmap_connection import MMAP_Connection
from xpra.server.source.fileprint_mixin import FilePrintMixin
from xpra.server.source.clipboard_connection import ClipboardConnection
from xpra.server.window.window_video_source import WindowVideoSource
from xpra.server.window.batch_config import DamageBatchConfig
Expand All @@ -43,27 +42,23 @@
from xpra.codecs.codec_constants import video_spec
from xpra.net import compression
from xpra.net.compression import compressed_wrapper, Compressed
from xpra.net.file_transfer import FileTransferHandler
from xpra.make_thread import start_thread
from xpra.os_util import platform_name, Queue, get_machine_id, monotonic_time, BytesIOClass, strtobytes
from xpra.os_util import platform_name, Queue, monotonic_time, BytesIOClass, strtobytes
from xpra.server.background_worker import add_work_item
from xpra.notifications.common import XPRA_BANDWIDTH_NOTIFICATION_ID, XPRA_IDLE_NOTIFICATION_ID
from xpra.platform.paths import get_icon_dir
from xpra.util import csv, std, typedict, merge_dicts, flatten_dict, notypedict, get_screen_info, envint, envbool, AtomicInteger, \
CLIENT_PING_TIMEOUT, DEFAULT_METADATA_SUPPORTED

NOYIELD = not envbool("XPRA_YIELD", False)
ADD_LOCAL_PRINTERS = envbool("XPRA_ADD_LOCAL_PRINTERS", False)
GRACE_PERCENT = envint("XPRA_GRACE_PERCENT", 90)
AV_SYNC_DELTA = envint("XPRA_AV_SYNC_DELTA", 0)
NEW_STREAM_SOUND = envbool("XPRA_NEW_STREAM_SOUND", True)
PING_DETAILS = envbool("XPRA_PING_DETAILS", True)
PING_TIMEOUT = envint("XPRA_PING_TIMEOUT", 60)
BANDWIDTH_DETECTION = envbool("XPRA_BANDWIDTH_DETECTION", True)
CONGESTION_WARNING_EVENT_COUNT = envint("XPRA_CONGESTION_WARNING_EVENT_COUNT", 10)
SKIP_METADATA = os.environ.get("XPRA_SKIP_METADATA", "").split(",")

PRINTER_LOCATION_STRING = os.environ.get("XPRA_PRINTER_LOCATION_STRING", "via xpra")
PROPERTIES_DEBUG = [x.strip() for x in os.environ.get("XPRA_WINDOW_PROPERTIES_DEBUG", "").split(",")]

MIN_PIXEL_RECALCULATE = envint("XPRA_MIN_PIXEL_RECALCULATE", 2000)
Expand All @@ -88,7 +83,7 @@
items are picked off by the separate 'encode' thread (see 'encode_loop')
and added to the damage_packet_queue.
"""
class ClientConnection(FileTransferHandler, AudioMixin, MMAP_Connection, ClipboardConnection):
class ClientConnection(AudioMixin, MMAP_Connection, ClipboardConnection, FilePrintMixin):

def __init__(self, protocol, disconnect_cb, idle_add, timeout_add, source_remove, setting_changed,
idle_timeout, idle_timeout_cb, idle_grace_timeout_cb,
Expand Down Expand Up @@ -124,11 +119,11 @@ def __init__(self, protocol, disconnect_cb, idle_add, timeout_add, source_remove
speaker_codecs, microphone_codecs,
default_quality, default_min_quality,
default_speed, default_min_speed))
FileTransferHandler.__init__(self, file_transfer)
AudioMixin.__init__(self, sound_properties, sound_source_plugin,
supports_speaker, supports_microphone, speaker_codecs, microphone_codecs)
MMAP_Connection.__init__(self, supports_mmap, mmap_filename, min_mmap_size)
ClipboardConnection.__init__(self)
FilePrintMixin.__init__(self, file_transfer)
global counter
self.counter = counter.increase()
self.close_event = Event()
Expand Down Expand Up @@ -291,7 +286,6 @@ def init_vars(self):
self.metadata_supported = ()
self.show_desktop_allowed = False
self.supports_transparency = False
self.printers = {}
self.vrefresh = -1
self.double_click_time = -1
self.double_click_distance = -1, -1
Expand Down Expand Up @@ -341,7 +335,6 @@ def close(self):
self.cancel_ping_echo_timers()
self.cancel_cursor_timer()
self.cancel_ping_timer()
self.remove_printers()
ds = self.dbus_server
if ds:
self.dbus_server = None
Expand Down Expand Up @@ -633,7 +626,7 @@ def parse_batch_int(value, varname):
self.proxy_version = c.strget("proxy.version")
self.proxy_version = c.strget("proxy.build.version", self.proxy_version)

#file transfers and printing:
#file transfers and printing caps:
self.parse_file_transfer_caps(c)
#general features:
self.zlib = c.boolget("zlib", True)
Expand Down Expand Up @@ -1135,7 +1128,7 @@ def addattr(k, name):
info["window-filter"] = finfo
info.update(self.get_features_info())
info.update(self.get_screen_info())
info["file-transfers"] = FileTransferHandler.get_info(self)
merge_dicts(info, FilePrintMixin.get_info(self))
merge_dicts(info, AudioMixin.get_info(self))
merge_dicts(info, MMAP_Connection.get_info(self))
return info
Expand Down Expand Up @@ -1169,8 +1162,6 @@ def battr(k, prop):
"double_click_distance" : "distance",
}.items():
dcinfo[name] = getattr(self, prop)
if self.printers:
info["printers"] = self.printers
return info

def get_window_info(self, window_ids=[]):
Expand Down Expand Up @@ -1359,113 +1350,6 @@ def send_webcam_stop(self, device, message):
self.send_async("webcam-stop", device, message)


######################################################################
# printing:
def set_printers(self, printers, password_file, auth, encryption, encryption_keyfile):
printlog("set_printers(%s, %s, %s, %s, %s) for %s", printers, password_file, auth, encryption, encryption_keyfile, self)
if self.machine_id==get_machine_id() and not ADD_LOCAL_PRINTERS:
self.printers = printers
printlog("local client with identical machine id,")
printlog(" not configuring local printers")
return
if not self.uuid:
printlog.warn("Warning: client did not supply a UUID,")
printlog.warn(" printer forwarding cannot be enabled")
return
from xpra.platform.pycups_printing import remove_printer
#remove the printers no longer defined
#or those whose definition has changed (and we will re-add them):
for k in tuple(self.printers.keys()):
cpd = self.printers.get(k)
npd = printers.get(k)
if cpd==npd:
#unchanged: make sure we don't try adding it again:
try:
del printers[k]
except:
pass
continue
if npd is None:
printlog("printer %s no longer exists", k)
else:
printlog("printer %s has been modified:", k)
printlog(" was %s", cpd)
printlog(" now %s", npd)
#remove it:
try:
del self.printers[k]
remove_printer(k)
except Exception as e:
printlog.error("Error: failed to remove printer %s:", k)
printlog.error(" %s", e)
del e
#expand it here so the xpraforwarder doesn't need to import anything xpra:
attributes = {"display" : os.environ.get("DISPLAY"),
"source" : self.uuid}
def makeabs(filename):
#convert to an absolute path since the backend may run as a different user:
return os.path.abspath(os.path.expanduser(filename))
if auth:
auth_password_file = None
try:
name, authclass, authoptions = auth
auth_password_file = authoptions.get("file")
log("file for %s / %s: '%s'", name, authclass, password_file)
except Exception as e:
log.error("Error: cannot forward authentication attributes to printer backend:")
log.error(" %s", e)
if auth_password_file or password_file:
attributes["password-file"] = makeabs(auth_password_file or password_file)
if encryption:
if not encryption_keyfile:
log.error("Error: no encryption keyfile found for printing")
else:
attributes["encryption"] = encryption
attributes["encryption-keyfile"] = makeabs(encryption_keyfile)
#if we can, tell it exactly where to connect:
if self.unix_socket_paths:
#prefer sockets in public paths:
spath = self.unix_socket_paths[0]
for x in self.unix_socket_paths:
if x.startswith("/tmp") or x.startswith("/var") or x.startswith("/run"):
spath = x
attributes["socket-path"] = spath
log("printer attributes: %s", attributes)
for k,props in printers.items():
if k not in self.printers:
self.setup_printer(k, props, attributes)

def setup_printer(self, name, props, attributes):
from xpra.platform.pycups_printing import add_printer
info = props.get("printer-info", "")
attrs = attributes.copy()
attrs["remote-printer"] = name
attrs["remote-device-uri"] = props.get("device-uri")
location = PRINTER_LOCATION_STRING
if self.hostname:
location = "on %s"
if PRINTER_LOCATION_STRING:
#ie: on FOO (via xpra)
location = "on %s (%s)" % (self.hostname, PRINTER_LOCATION_STRING)
try:
def printer_added():
#once the printer has been added, register it in the list
#(so it will be removed on exit)
printlog.info("the remote printer '%s' has been configured", name)
self.printers[name] = props
add_printer(name, props, info, location, attrs, success_cb=printer_added)
except Exception as e:
printlog.warn("Warning: failed to add printer %s: %s", name, e)
printlog("setup_printer(%s, %s, %s)", name, props, attributes, exc_info=True)

def remove_printers(self):
if self.machine_id==get_machine_id() and not ADD_LOCAL_PRINTERS:
return
printers = self.printers.copy()
self.printers = {}
for k in printers:
from xpra.platform.pycups_printing import remove_printer
remove_printer(k)


def send_client_command(self, *args):
Expand Down
147 changes: 147 additions & 0 deletions src/xpra/server/source/fileprint_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
# This file is part of Xpra.
# Copyright (C) 2010-2018 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import os

from xpra.log import Logger
log = Logger("printing")

from xpra.util import envbool
from xpra.os_util import get_machine_id
from xpra.net.file_transfer import FileTransferHandler


ADD_LOCAL_PRINTERS = envbool("XPRA_ADD_LOCAL_PRINTERS", False)
PRINTER_LOCATION_STRING = os.environ.get("XPRA_PRINTER_LOCATION_STRING", "via xpra")


class FilePrintMixin(FileTransferHandler):

def __init__(self):
self.printers = {}

def cleanup(self):
self.remove_printers()

def parse_client_caps(self, c):
pass

def get_caps(self):
return {}

def get_info(self):
return {
"printers" : self.printers,
"file-transfers" : FileTransferHandler.get_info(self),
}

######################################################################
# printing:
def set_printers(self, printers, password_file, auth, encryption, encryption_keyfile):
log("set_printers(%s, %s, %s, %s, %s) for %s", printers, password_file, auth, encryption, encryption_keyfile, self)
if self.machine_id==get_machine_id() and not ADD_LOCAL_PRINTERS:
self.printers = printers
log("local client with identical machine id,")
log(" not configuring local printers")
return
if not self.uuid:
log.warn("Warning: client did not supply a UUID,")
log.warn(" printer forwarding cannot be enabled")
return
from xpra.platform.pycups_printing import remove_printer
#remove the printers no longer defined
#or those whose definition has changed (and we will re-add them):
for k in tuple(self.printers.keys()):
cpd = self.printers.get(k)
npd = printers.get(k)
if cpd==npd:
#unchanged: make sure we don't try adding it again:
try:
del printers[k]
except:
pass
continue
if npd is None:
log("printer %s no longer exists", k)
else:
log("printer %s has been modified:", k)
log(" was %s", cpd)
log(" now %s", npd)
#remove it:
try:
del self.printers[k]
remove_printer(k)
except Exception as e:
log.error("Error: failed to remove printer %s:", k)
log.error(" %s", e)
del e
#expand it here so the xpraforwarder doesn't need to import anything xpra:
attributes = {"display" : os.environ.get("DISPLAY"),
"source" : self.uuid}
def makeabs(filename):
#convert to an absolute path since the backend may run as a different user:
return os.path.abspath(os.path.expanduser(filename))
if auth:
auth_password_file = None
try:
name, authclass, authoptions = auth
auth_password_file = authoptions.get("file")
log("file for %s / %s: '%s'", name, authclass, password_file)
except Exception as e:
log.error("Error: cannot forward authentication attributes to printer backend:")
log.error(" %s", e)
if auth_password_file or password_file:
attributes["password-file"] = makeabs(auth_password_file or password_file)
if encryption:
if not encryption_keyfile:
log.error("Error: no encryption keyfile found for printing")
else:
attributes["encryption"] = encryption
attributes["encryption-keyfile"] = makeabs(encryption_keyfile)
#if we can, tell it exactly where to connect:
if self.unix_socket_paths:
#prefer sockets in public paths:
spath = self.unix_socket_paths[0]
for x in self.unix_socket_paths:
if x.startswith("/tmp") or x.startswith("/var") or x.startswith("/run"):
spath = x
attributes["socket-path"] = spath
log("printer attributes: %s", attributes)
for k,props in printers.items():
if k not in self.printers:
self.setup_printer(k, props, attributes)

def setup_printer(self, name, props, attributes):
from xpra.platform.pycups_printing import add_printer
info = props.get("printer-info", "")
attrs = attributes.copy()
attrs["remote-printer"] = name
attrs["remote-device-uri"] = props.get("device-uri")
location = PRINTER_LOCATION_STRING
if self.hostname:
location = "on %s"
if PRINTER_LOCATION_STRING:
#ie: on FOO (via xpra)
location = "on %s (%s)" % (self.hostname, PRINTER_LOCATION_STRING)
try:
def printer_added():
#once the printer has been added, register it in the list
#(so it will be removed on exit)
log.info("the remote printer '%s' has been configured", name)
self.printers[name] = props
add_printer(name, props, info, location, attrs, success_cb=printer_added)
except Exception as e:
log.warn("Warning: failed to add printer %s: %s", name, e)
log("setup_printer(%s, %s, %s)", name, props, attributes, exc_info=True)

def remove_printers(self):
if self.machine_id==get_machine_id() and not ADD_LOCAL_PRINTERS:
return
printers = self.printers.copy()
self.printers = {}
for k in printers:
from xpra.platform.pycups_printing import remove_printer
remove_printer(k)

0 comments on commit 0993f20

Please sign in to comment.