xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #2351: skip-clientconnection-mixins.patch

File skip-clientconnection-mixins.patch, 15.7 KB (added by Antoine Martin, 16 months ago)

implementation - causes server hangs on control-c

  • xpra/server/server_base.py

     
    396396        send_ui = ui_client and not is_request
    397397        self.idle_add(self._process_hello_ui, ss, c, auth_caps, send_ui, share_count)
    398398
    399     def get_client_connection_class(self, _caps):
    400         from xpra.server.source.client_connection import ClientConnection
    401         return ClientConnection
     399    def get_client_connection_class(self, caps):
     400        from xpra.server.source.client_connection_factory import get_client_connection_class
     401        return get_client_connection_class(caps)
    402402
    403403
    404404    def _process_hello_ui(self, ss, c, auth_caps, send_ui, share_count):
  • xpra/server/source/client_connection.py

     
    1313
    1414from xpra.make_thread import start_thread
    1515from xpra.os_util import monotonic_time
    16 from xpra.util import merge_dicts, notypedict, envbool, envint, typedict, AtomicInteger
     16from xpra.util import notypedict, envbool, envint, typedict, AtomicInteger
    1717from xpra.net.compression import compressed_wrapper, Compressed
     18from xpra.server.source.stub_source_mixin import StubSourceMixin
    1819from xpra.server.source.source_stats import GlobalPerformanceStatistics
    19 from xpra.server.source.clientinfo_mixin import ClientInfoMixin
    20 from xpra.server import server_features
    2120from xpra.log import Logger
    2221
    23 CC_BASES = [ClientInfoMixin]
    24 #TODO: notifications mixin
    25 if server_features.clipboard:
    26     from xpra.server.source.clipboard_connection import ClipboardConnection
    27     CC_BASES.append(ClipboardConnection)
    28 if server_features.audio:
    29     from xpra.server.source.audio_mixin import AudioMixin
    30     CC_BASES.append(AudioMixin)
    31 if server_features.webcam:
    32     from xpra.server.source.webcam_mixin import WebcamMixin
    33     CC_BASES.append(WebcamMixin)
    34 if server_features.fileprint:
    35     from xpra.server.source.fileprint_mixin import FilePrintMixin
    36     CC_BASES.append(FilePrintMixin)
    37 if server_features.mmap:
    38     from xpra.server.source.mmap_connection import MMAP_Connection
    39     CC_BASES.append(MMAP_Connection)
    40 if server_features.input_devices:
    41     from xpra.server.source.input_mixin import InputMixin
    42     CC_BASES.append(InputMixin)
    43 if server_features.dbus:
    44     from xpra.server.source.dbus_mixin import DBUS_Mixin
    45     CC_BASES.append(DBUS_Mixin)
    46 if server_features.network_state:
    47     from xpra.server.source.networkstate_mixin import NetworkStateMixin
    48     CC_BASES.append(NetworkStateMixin)
    49 if server_features.display:
    50     from xpra.server.source.clientdisplay_mixin import ClientDisplayMixin
    51     CC_BASES.append(ClientDisplayMixin)
    52 if server_features.windows:
    53     from xpra.server.source.windows_mixin import WindowsMixin
    54     CC_BASES.append(WindowsMixin)
    55     #must be after windows mixin so it can assume "self.send_windows" is set
    56     if server_features.encoding:
    57         from xpra.server.source.encodings_mixin import EncodingsMixin
    58         CC_BASES.append(EncodingsMixin)
    59     if server_features.audio and server_features.av_sync:
    60         from xpra.server.source.avsync_mixin import AVSyncMixin
    61         CC_BASES.append(AVSyncMixin)
    62 from xpra.server.source.idle_mixin import IdleMixin
    63 CC_BASES.append(IdleMixin)
    64 CC_BASES = tuple(CC_BASES)
    65 ClientConnectionClass = type('ClientConnectionClass', CC_BASES, {})
    66 
    6722log = Logger("server")
    6823elog = Logger("encoding")
    6924proxylog = Logger("proxy")
     
    7025notifylog = Logger("notify")
    7126bandwidthlog = Logger("bandwidth")
    7227
    73 log("ClientConnectionClass%s", CC_BASES)
    7428
    75 
    7629BANDWIDTH_DETECTION = envbool("XPRA_BANDWIDTH_DETECTION", True)
    7730MIN_BANDWIDTH = envint("XPRA_MIN_BANDWIDTH", 5*1024*1024)
    7831AUTO_BANDWIDTH_PCT = envint("XPRA_AUTO_BANDWIDTH_PCT", 80)
     
    10053and added to the damage_packet_queue.
    10154"""
    10255
    103 class ClientConnection(ClientConnectionClass):
     56class ClientConnection(StubSourceMixin):
    10457
    10558    def __init__(self, protocol, disconnect_cb, session_name, server,
    106                  idle_add, timeout_add, source_remove,
    10759                 setting_changed,
    10860                 socket_dir, unix_socket_paths, log_disconnect, bandwidth_limit, bandwidth_detection,
    10961                 ):
     
    11567        self.disconnect = disconnect_cb
    11668        self.session_name = session_name
    11769
    118         for bc in CC_BASES:
    119             try:
    120                 bc.__init__(self)
    121                 bc.init_from(self, protocol, server)
    122             except Exception as e:
    123                 raise Exception("failed to initialize %s: %s" % (bc, e)) from None
     70        self.socket_dir = socket_dir
     71        self.unix_socket_paths = unix_socket_paths
     72        self.log_disconnect = log_disconnect
    12473
    125         for c in CC_BASES:
    126             c.init_state(self)
     74        self.setting_changed = setting_changed
     75        # network constraints:
     76        self.server_bandwidth_limit = bandwidth_limit
     77        self.bandwidth_detection = bandwidth_detection
    12778
     79    def init_state(self):
    12880        #holds actual packets ready for sending (already encoded)
    12981        #these packets are picked off by the "protocol" via 'next_packet()'
    13082        #format: packet, wid, pixels, start_send_cb, end_send_cb
     
    13890        self.encode_work_queue = None
    13991        self.encode_thread = None
    14092        self.ordinary_packets = []
    141         self.socket_dir = socket_dir
    142         self.unix_socket_paths = unix_socket_paths
    143         self.log_disconnect = log_disconnect
    144         self.idle_add = idle_add
    145         self.timeout_add = timeout_add
    146         self.source_remove = source_remove
    14793
    148         self.setting_changed = setting_changed
    149         # network constraints:
    150         self.server_bandwidth_limit = bandwidth_limit
    151         self.bandwidth_detection = bandwidth_detection
    152 
    15394        #these statistics are shared by all WindowSource instances:
    15495        self.statistics = GlobalPerformanceStatistics()
    15596
     
    15798
    15899        # ready for processing:
    159100        self.queue_encode = self.start_queue_encode
    160         protocol.set_packet_source(self.next_packet)
     101        self.protocol.set_packet_source(self.next_packet)
    161102
    162103
    163104    def __repr__(self):
     
    191132    def is_closed(self):
    192133        return self.close_event.isSet()
    193134
    194     def close(self):
    195         log("%s.close()", self)
    196         for c in CC_BASES:
    197             c.cleanup(self)
     135    def cleanup(self):
    198136        self.close_event.set()
    199137        self.protocol = None
    200138
     
    254192                ws.bandwidth_limit = max(MIN_BANDWIDTH//10, bandwidth_limit*weight//total_weight)
    255193
    256194
    257     def parse_hello(self, c):
    258         self.ui_client = c.boolget("ui_client", True)
    259         self.wants_encodings = c.boolget("wants_encodings", self.ui_client)
    260         self.wants_display = c.boolget("wants_display", self.ui_client)
    261         self.wants_events = c.boolget("wants_events", False)
    262         self.wants_aliases = c.boolget("wants_aliases", True)
    263         self.wants_versions = c.boolget("wants_versions", True)
    264         self.wants_features = c.boolget("wants_features", True)
    265         self.wants_default_cursor = c.boolget("wants_default_cursor", False)
    266 
    267         for mixin in CC_BASES:
    268             mixin.parse_client_caps(self, c)
    269 
     195    def parse_client_caps(self, c):
    270196        #general features:
    271197        self.info_namespace = c.boolget("info-namespace")
    272198        self.send_notifications = c.boolget("notifications")
     
    430356        self.send(*parts, **kwargs)
    431357
    432358
    433     def send_hello(self, server_capabilities):
    434         capabilities = server_capabilities.copy()
    435         for bc in CC_BASES:
    436             merge_dicts(capabilities, bc.get_caps(self))
    437         self.send("hello", capabilities)
    438         self.hello_sent = True
    439 
    440 
    441359    ######################################################################
    442360    # info:
    443361    def get_info(self) -> dict:
     
    459377                         "connection"       : p.get_info(),
    460378                         })
    461379        info.update(self.get_features_info())
    462         for bc in CC_BASES:
    463             try:
    464                 merge_dicts(info, bc.get_info(self))
    465             except Exception as e:
    466                 log("merge_dicts on %s", bc, exc_info=True)
    467                 log.error("Error: cannot add information from %s:", bc)
    468                 log.error(" %s", e)
    469380        return info
    470381
    471382    def get_features_info(self) -> dict:
  • xpra/server/source/client_connection_factory.py

     
     1# -*- coding: utf-8 -*-
     2# This file is part of Xpra.
     3# Copyright (C) 2010-2020 Antoine Martin <antoine@xpra.org>
     4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     5# later version. See the file COPYING for details.
     6
     7from xpra.server import server_features
     8from xpra.util import merge_dicts
     9
     10
     11def get_client_connection_class(caps):
     12    from xpra.server.source.client_connection import ClientConnection
     13    CC = [ClientConnection]
     14    from xpra.server.source.clientinfo_mixin import ClientInfoMixin
     15    CC.append(ClientInfoMixin)
     16    #TODO: notifications mixin
     17    if server_features.clipboard:
     18        from xpra.server.source.clipboard_connection import ClipboardConnection
     19        CC.append(ClipboardConnection)
     20    if server_features.audio:
     21        from xpra.server.source.audio_mixin import AudioMixin
     22        CC.append(AudioMixin)
     23    if server_features.webcam:
     24        from xpra.server.source.webcam_mixin import WebcamMixin
     25        CC.append(WebcamMixin)
     26    if server_features.fileprint:
     27        from xpra.server.source.fileprint_mixin import FilePrintMixin
     28        CC.append(FilePrintMixin)
     29    if server_features.mmap:
     30        from xpra.server.source.mmap_connection import MMAP_Connection
     31        CC.append(MMAP_Connection)
     32    if server_features.input_devices:
     33        from xpra.server.source.input_mixin import InputMixin
     34        CC.append(InputMixin)
     35    if server_features.dbus:
     36        from xpra.server.source.dbus_mixin import DBUS_Mixin
     37        CC.append(DBUS_Mixin)
     38    if server_features.network_state:
     39        from xpra.server.source.networkstate_mixin import NetworkStateMixin
     40        CC.append(NetworkStateMixin)
     41    if server_features.display:
     42        from xpra.server.source.clientdisplay_mixin import ClientDisplayMixin
     43        CC.append(ClientDisplayMixin)
     44    if server_features.windows:
     45        from xpra.server.source.windows_mixin import WindowsMixin
     46        CC.append(WindowsMixin)
     47        #must be after windows mixin so it can assume "self.send_windows" is set
     48        if server_features.encoding:
     49            from xpra.server.source.encodings_mixin import EncodingsMixin
     50            CC.append(EncodingsMixin)
     51        if server_features.audio and server_features.av_sync:
     52            from xpra.server.source.avsync_mixin import AVSyncMixin
     53            CC.append(AVSyncMixin)
     54    from xpra.server.source.idle_mixin import IdleMixin
     55    CC.append(IdleMixin)
     56
     57    from xpra.log import Logger
     58    log = Logger("server")
     59    NEEDED_CC_BASES = []
     60    for c in CC:
     61        r = c.is_needed(caps)
     62        log("%s.is_needed()=%s", c, r)
     63        if r:
     64            NEEDED_CC_BASES.append(c)
     65    CC_BASES = tuple(CC)
     66    ClientConnectionClass = type('ClientConnectionClass', CC_BASES, {})
     67    log("get_client_connection_class(..)=%s for base classes %s",
     68        ClientConnectionClass, CC_BASES)
     69
     70    class ClientConnectionMuxer(ClientConnectionClass):
     71
     72        def __init__(self, protocol, disconnect_cb, session_name, server,
     73                     idle_add, timeout_add, source_remove,
     74                     *args):
     75            self.idle_add = idle_add
     76            self.timeout_add = timeout_add
     77            self.source_remove = source_remove
     78            for bc in CC_BASES:
     79                try:
     80                    if bc==ClientConnection:
     81                        initargs = [protocol, disconnect_cb, session_name, server]+list(args)
     82                    else:
     83                        initargs = ()
     84                    bc.__init__(self, *initargs)
     85                    bc.init_from(self, protocol, server)
     86                except Exception as e:
     87                    raise Exception("failed to initialize %s: %s" % (bc, e)) from None
     88   
     89            for c in CC_BASES:
     90                c.init_state(self)
     91
     92        def close(self):
     93            log("%s.close()", self)
     94            for bc in reversed(CC_BASES):
     95                log("%s.cleanup()", bc)
     96                c.cleanup(self)
     97
     98        def send_hello(self, server_capabilities):
     99            capabilities = server_capabilities.copy()
     100            for bc in CC_BASES:
     101                log("%s.get_caps()", bc)
     102                merge_dicts(capabilities, bc.get_caps(self))
     103            self.send("hello", capabilities)
     104            self.hello_sent = True
     105
     106        def get_info(self) -> dict:
     107            info = {}
     108            for bc in CC_BASES:
     109                log("%s.get_info()", bc)
     110                try:
     111                    merge_dicts(info, bc.get_info(self))
     112                except Exception as e:
     113                    log("merge_dicts on %s", bc, exc_info=True)
     114                    log.error("Error: cannot add information from %s:", bc)
     115                    log.error(" %s", e)
     116            return info
     117
     118        def parse_hello(self, c):
     119            self.ui_client = c.boolget("ui_client", True)
     120            self.wants_encodings = c.boolget("wants_encodings", self.ui_client)
     121            self.wants_display = c.boolget("wants_display", self.ui_client)
     122            self.wants_events = c.boolget("wants_events", False)
     123            self.wants_aliases = c.boolget("wants_aliases", True)
     124            self.wants_versions = c.boolget("wants_versions", True)
     125            self.wants_features = c.boolget("wants_features", True)
     126            self.wants_default_cursor = c.boolget("wants_default_cursor", False)
     127            for bc in CC_BASES:
     128                log("%s.parse_client_caps(..)", bc)
     129                bc.parse_client_caps(self, c)
     130
     131    return ClientConnectionMuxer
  • xpra/server/source/mmap_connection.py

     
    1616
    1717class MMAP_Connection(StubSourceMixin):
    1818
     19    @classmethod
     20    def is_needed(cls, caps):
     21        #pre 2.3 clients;
     22        if caps.strget("mmap_file"):
     23            return True
     24        v = caps.rawget("mmap")
     25        #we should be receiving a dict with mmap attributes
     26        #(but pre v4 clients also send a boolean telling us if mmap is supported by the platform..)
     27        return isinstance(v, dict)
     28
    1929    def __init__(self):
    2030        self.supports_mmap = False
    2131        self.mmap_filename = None
  • xpra/server/source/stub_source_mixin.py

     
    11# -*- coding: utf-8 -*-
    22# This file is part of Xpra.
    3 # Copyright (C) 2018 Antoine Martin <antoine@xpra.org>
     3# Copyright (C) 2018-2020 Antoine Martin <antoine@xpra.org>
    44# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
    55# later version. See the file COPYING for details.
    66
     
    1111class StubSourceMixin:
    1212
    1313    """
     14    Is this mixin needed for the caps given?
     15    """
     16    @classmethod
     17    def is_needed(cls, caps):
     18        return True
     19
     20    def __init__(self, *_args):
     21        pass
     22
     23    """
    1424    Initialize state attributes.
    1525    """
    1626    def init_state(self):