Hide keyboard shortcuts

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. 

6 

7from xpra.server import server_features 

8from xpra.util import merge_dicts, typedict 

9from xpra.log import Logger 

10 

11log = Logger("server") 

12 

13 

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) 

73 

74 class ClientConnectionMuxer(ClientConnectionClass): 

75 

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 

93 

94 for c in CC_BASES: 

95 c.init_state(self) 

96 self.run() 

97 

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 

109 

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 

117 

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 

134 

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) 

157 

158 return ClientConnectionMuxer