Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/server/source/client_connection_factory.py : 87%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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.
7from xpra.server import server_features
8from xpra.util import merge_dicts, typedict
9from xpra.log import Logger
11log = Logger("server")
14def get_client_connection_class(caps):
15 from xpra.server.source.clientinfo_mixin import ClientInfoMixin
16 CC = [ClientInfoMixin]
17 #TODO: notifications mixin
18 if server_features.notifications:
19 from xpra.server.source.notification_mixin import NotificationMixin
20 CC.append(NotificationMixin)
21 if server_features.clipboard:
22 from xpra.server.source.clipboard_connection import ClipboardConnection
23 CC.append(ClipboardConnection)
24 if server_features.audio:
25 from xpra.server.source.audio_mixin import AudioMixin
26 CC.append(AudioMixin)
27 if server_features.webcam:
28 from xpra.server.source.webcam_mixin import WebcamMixin
29 CC.append(WebcamMixin)
30 if server_features.fileprint:
31 from xpra.server.source.fileprint_mixin import FilePrintMixin
32 CC.append(FilePrintMixin)
33 if server_features.mmap:
34 from xpra.server.source.mmap_connection import MMAP_Connection
35 CC.append(MMAP_Connection)
36 if server_features.input_devices:
37 from xpra.server.source.input_mixin import InputMixin
38 CC.append(InputMixin)
39 if server_features.dbus:
40 from xpra.server.source.dbus_mixin import DBUS_Mixin
41 CC.append(DBUS_Mixin)
42 if server_features.network_state:
43 from xpra.server.source.networkstate_mixin import NetworkStateMixin
44 CC.append(NetworkStateMixin)
45 if server_features.shell:
46 from xpra.server.source.shell_mixin import ShellMixin
47 CC.append(ShellMixin)
48 if server_features.display:
49 from xpra.server.source.clientdisplay_mixin import ClientDisplayMixin
50 CC.append(ClientDisplayMixin)
51 if server_features.windows:
52 from xpra.server.source.windows_mixin import WindowsMixin
53 CC.append(WindowsMixin)
54 #must be after windows mixin so it can assume "self.send_windows" is set
55 if server_features.encoding:
56 from xpra.server.source.encodings_mixin import EncodingsMixin
57 CC.append(EncodingsMixin)
58 if server_features.audio and server_features.av_sync:
59 from xpra.server.source.avsync_mixin import AVSyncMixin
60 CC.append(AVSyncMixin)
61 from xpra.server.source.idle_mixin import IdleMixin
62 CC.append(IdleMixin)
63 CC_BASES = []
64 for c in CC:
65 r = c.is_needed(caps)
66 log("get_client_connection_class(..) %s enabled=%s", c.__name__.split(".")[-1], r)
67 if r:
68 CC_BASES.append(c)
69 from xpra.server.source.client_connection import ClientConnection
70 CC_BASES = tuple([ClientConnection]+list(CC_BASES))
71 ClientConnectionClass = type('ClientConnectionClass', CC_BASES, {})
72 log("ClientConnectionClass%s", CC_BASES)
74 class ClientConnectionMuxer(ClientConnectionClass):
76 def __init__(self, protocol, disconnect_cb, session_name, server,
77 idle_add, timeout_add, source_remove,
78 *args):
79 self.idle_add = idle_add
80 self.timeout_add = timeout_add
81 self.source_remove = source_remove
82 for bc in CC_BASES:
83 try:
84 if bc==ClientConnection:
85 initargs = [protocol, disconnect_cb, session_name]+list(args)
86 else:
87 initargs = ()
88 bc.__init__(self, *initargs)
89 bc.init_from(self, protocol, server)
90 except Exception as e:
91 log.error("%s.__init__(..)", bc, exc_info=True)
92 raise Exception("failed to initialize %s: %s" % (bc, e)) from None
94 for c in CC_BASES:
95 c.init_state(self)
96 self.run()
98 def close(self):
99 log("%s.close()", self)
100 for bc in reversed(CC_BASES):
101 log("%s.cleanup()", bc)
102 try:
103 bc.cleanup(self)
104 except Exception as e:
105 log("%s.cleanup()", bc, exc_info=True)
106 log.error("Error closing connection")
107 log.error(" %s", e)
108 raise Exception("failed to initialize %s: %s" % (bc, e)) from None
110 def send_hello(self, server_capabilities):
111 capabilities = server_capabilities.copy()
112 for bc in CC_BASES:
113 log("%s.get_caps()", bc)
114 merge_dicts(capabilities, bc.get_caps(self))
115 self.send("hello", capabilities)
116 self.hello_sent = True
118 def get_info(self) -> dict:
119 def module_name(m):
120 name = str(m.__name__.split(".")[-1])
121 return name.replace("Mixin", "").replace("Connection", "").rstrip("_")
122 info = {
123 "modules" : tuple(module_name(x) for x in CC_BASES),
124 }
125 for bc in CC_BASES:
126 log("%s.get_info()", bc)
127 try:
128 merge_dicts(info, bc.get_info(self))
129 except Exception as e:
130 log("merge_dicts on %s", bc, exc_info=True)
131 log.error("Error: cannot add information from %s:", bc)
132 log.error(" %s", e)
133 return info
135 def parse_hello(self, c : typedict):
136 self.ui_client = c.boolget("ui_client", True)
137 self.wants_encodings = c.boolget("wants_encodings", self.ui_client)
138 self.wants_display = c.boolget("wants_display", self.ui_client)
139 self.wants_events = c.boolget("wants_events", False)
140 self.wants_aliases = c.boolget("wants_aliases", True)
141 self.wants_versions = c.boolget("wants_versions", True)
142 self.wants_features = c.boolget("wants_features", True)
143 self.wants_default_cursor = c.boolget("wants_default_cursor", False)
144 for bc in CC_BASES:
145 log("%s.parse_client_caps(..)", bc)
146 bc.parse_client_caps(self, c)
147 #log client info:
148 cinfo = self.get_connect_info()
149 for i,ci in enumerate(cinfo):
150 log.info("%s%s", ["", " "][int(i>0)], ci)
151 if self.client_proxy:
152 from xpra.version_util import version_compat_check
153 msg = version_compat_check(self.proxy_version)
154 if msg:
155 proxylog = Logger("proxy")
156 proxylog.warn("Warning: proxy version may not be compatible: %s", msg)
158 return ClientConnectionMuxer