[X2Go-Commits] python-x2go.git - twofactorauth (branch) updated: 0.1.1.4-242-g63ac948

X2Go dev team git-admin at x2go.org
Sat Sep 14 15:57:31 CEST 2013


The branch, twofactorauth has been updated
       via  63ac948ac2d787b9d82dc086d316f7c7b1246cf3 (commit)
      from  97c0d9d61117c7924dd368053cab595704efbccb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
-----------------------------------------------------------------------

Summary of changes:
 debian/changelog                  |    6 ++
 x2go/backends/control/_stdout.py  |   52 ++++-----
 x2go/backends/proxy/_nx3.py       |    4 +-
 x2go/backends/proxy/base.py       |   22 ++--
 x2go/backends/terminal/_stdout.py |  216 +++++++++++++++++++++----------------
 x2go/client.py                    |    4 +-
 x2go/forward.py                   |   44 ++++----
 x2go/registry.py                  |    4 +-
 x2go/session.py                   |   55 +++++-----
 x2go/sftpserver.py                |    3 +
 x2go/sshproxy.py                  |    6 ++
 x2go/x2go_exceptions.py           |    1 +
 12 files changed, 234 insertions(+), 183 deletions(-)

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index bb03bc8..98d3ae5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -128,6 +128,12 @@ python-x2go (0.1.2.0-0~x2go1) UNRELEASED; urgency=low
     - Allow custom commands to be desktop sessions.
     - X2goSession instances cannot raise X2goClientExceptions.
     - Be more tolerant against suspension failures while taking over a session.
+    - Use Paramiko transport compression if available.
+    - Prohibit simultaneous calls to terminal_session.share_local_folders().
+    - Cache SSH transport's getpeername() and get_username().
+    - Catch session startup failures due to faulty port forwarding tunnels
+      and make the notifiable via hooks.
+    - Properly set setkbd value for x2gostartagent and x2goresume-session.
   * Depend on python-xlib.
 
  -- Mike Gabriel <mike.gabriel at das-netzwerkteam.de>  Sat, 28 Sep 2012 01:44:21 +0100
diff --git a/x2go/backends/control/_stdout.py b/x2go/backends/control/_stdout.py
index a5d08ba..74c2350 100644
--- a/x2go/backends/control/_stdout.py
+++ b/x2go/backends/control/_stdout.py
@@ -122,6 +122,8 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
         self._session_auth_rsakey = None
         self._remote_home = None
         self._remote_group = {}
+        self._remote_username = None
+        self._remote_peername = None
 
         self._server_features = None
 
@@ -306,26 +308,26 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
         Returns the control session's remote username.
 
         """
-        if self.get_transport() is not None:
-            try:
-                return self.get_transport().get_username()
-            except:
-                raise x2go_exceptions.X2goControlSessionException('Lost connection to X2Go server')
-        else:
-            return None
+        if self._remote_username is None:
+            if self.get_transport() is not None:
+                try:
+                    self._remote_username = self.get_transport().get_username()
+                except:
+                    raise x2go_exceptions.X2goControlSessionException('Lost connection to X2Go server')
+        return self._remote_username
 
     def remote_peername(self):
         """\
         Returns the control session's remote host (name or ip).
 
         """
-        if self.get_transport() is not None:
-            try:
-                return self.get_transport().getpeername()
-            except:
-                raise x2go_exceptions.X2goControlSessionException('Lost connection to X2Go server')
-        else:
-            return None
+        if self._remote_peername is None:
+            if self.get_transport() is not None:
+                try:
+                    self._remote_peername = self.get_transport().getpeername()
+                except:
+                    raise x2go_exceptions.X2goControlSessionException('Lost connection to X2Go server')
+        return self._remote_peername
 
     @property
     def _x2go_session_auth_rsakey(self):
@@ -476,6 +478,11 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
                                            key_filename=key_filename, timeout=timeout, allow_agent=allow_agent, 
                                            look_for_keys=look_for_keys)
 
+                # since Paramiko 1.7.7.1 there is compression available, let's use it if present...
+                t = self.get_transport()
+                if hasattr(t, 'use_compression'):
+                    t.use_compression(compress=True)
+
             except paramiko.AuthenticationException, e:
                 self.close()
                 if password:
@@ -830,7 +837,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
         """
         return self.resume(**kwargs)
 
-    def resume(self, session_name=None, session_instance=None, **kwargs):
+    def resume(self, session_name=None, session_instance=None, session_list=None, **kwargs):
         """\
         Resume a running/suspended X2Go session. 
 
@@ -845,7 +852,10 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
             raise x2go_exceptions.X2goUserException('remote user %s is not allowed to run X2Go commands' % self.get_transport().get_username())
 
         if session_name is not None:
-            session_info = self.list_sessions()[session_name]
+            if session_list:
+                session_info = session_list[session_name]
+            else:
+                session_info = self.list_sessions()[session_name]
         else:
             session_info = None
 
@@ -862,16 +872,10 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
 
         _success = False
         if session_name is not None:
-            try:
-                _success = _terminal.resume()
-            except x2go_exceptions.X2goFwTunnelException:
-                pass
+            _success = _terminal.resume()
 
         else:
-            try:
-                _success = _terminal.start()
-            except x2go_exceptions.X2goFwTunnelException:
-                pass
+            _success = _terminal.start()
 
         if _success:
             while not _terminal.ok():
diff --git a/x2go/backends/proxy/_nx3.py b/x2go/backends/proxy/_nx3.py
index e5ada98..7005178 100644
--- a/x2go/backends/proxy/_nx3.py
+++ b/x2go/backends/proxy/_nx3.py
@@ -164,11 +164,11 @@ options=%s""" % ( self.proxy_options['xkbrules'],
         self.logger('NX3 Proxy mode is server, cookie=%s, host=127.0.0.1, port=%s.' % (self.session_info.cookie, self.session_info.graphics_port,), loglevel=log.loglevel_DEBUG)
         self.logger('NX3 proxy writes session log to %s.' % os.path.join(self.session_info.local_container, 'session.log'), loglevel=log.loglevel_DEBUG)
 
-        p = base.X2goProxyBASE.start_proxy(self)
+        p, p_ok = base.X2goProxyBASE.start_proxy(self)
 
         if self.ok():
             self.logger('NX3 proxy is up and running.', loglevel=log.loglevel_INFO)
         else:
             self.logger('Bringing up NX3 proxy failed.', loglevel=log.loglevel_ERROR)
 
-        return p
+        return p, self.ok()
diff --git a/x2go/backends/proxy/base.py b/x2go/backends/proxy/base.py
index 0c1586c..028190a 100644
--- a/x2go/backends/proxy/base.py
+++ b/x2go/backends/proxy/base.py
@@ -168,7 +168,7 @@ class X2goProxyBASE(threading.Thread):
             return None
 
         try:
-            os.mkdir(self.session_info.local_container)
+            os.makedirs(self.session_info.local_container)
         except OSError, e:
             if e.errno == 17:
                 # file exists
@@ -273,15 +273,17 @@ class X2goProxyBASE(threading.Thread):
             self.logger('waiting for proxy to come up: 0.4s x %s' % _count, loglevel=log.loglevel_DEBUG)
             gevent.sleep(.4)
 
-        # also wait for fw_tunnel to become active
-        _count = 0
-        _maxwait = 40
-        while not self.fw_tunnel.is_active and _count < _maxwait:
-            _count += 1
-            self.logger('waiting for port fw tunnel to come up: 0.5s x %s' % _count, loglevel=log.loglevel_DEBUG)
-            gevent.sleep(.5)
+        if self.proxy:
+
+            # also wait for fw_tunnel to become active
+            _count = 0
+            _maxwait = 40
+            while not self.fw_tunnel.is_active and not self.fw_tunnel.failed and _count < _maxwait:
+                _count += 1
+                self.logger('waiting for port fw tunnel to come up: 0.5s x %s' % _count, loglevel=log.loglevel_DEBUG)
+                gevent.sleep(.5)
 
-        return self.proxy
+        return self.proxy, bool(self.proxy) and self.fw_tunnel.is_active
 
     def ok(self):
         """\
@@ -291,4 +293,4 @@ class X2goProxyBASE(threading.Thread):
         @rtype C{bool}
 
         """
-        return bool(self.proxy and self.proxy.poll() is None)
+        return bool(self.proxy and self.proxy.poll() is None) and self.fw_tunnel.is_active
diff --git a/x2go/backends/terminal/_stdout.py b/x2go/backends/terminal/_stdout.py
index 4c401a7..7199ad8 100644
--- a/x2go/backends/terminal/_stdout.py
+++ b/x2go/backends/terminal/_stdout.py
@@ -322,6 +322,7 @@ class X2goTerminalSessionSTDOUT(object):
         else:
             self.client_instance = None
 
+        self._share_local_folder_busy = False
         self._mk_sessions_rootdir(self.params.rootdir)
 
         self.session_info = session_info
@@ -366,7 +367,7 @@ class X2goTerminalSessionSTDOUT(object):
     def _mk_sessions_rootdir(self, d):
 
         try:
-            os.mkdir(d)
+            os.makedirs(d)
         except OSError, e:
             if e.errno == 17:
                 # file exists
@@ -504,6 +505,8 @@ class X2goTerminalSessionSTDOUT(object):
                 self.reverse_tunnels[self.session_info.name]['sshfs'] = (self.session_info.sshfs_port, _tunnel)
                 _tunnel.start()
                 self.active_threads.append(_tunnel)
+                while not _tunnel.ready:
+                    gevent.sleep(.1)
 
         else:
             # tunnel has already been started and might simply need a resume call
@@ -539,7 +542,7 @@ class X2goTerminalSessionSTDOUT(object):
 
         spool_dir = os.path.join(self.session_info.local_container, 'spool')
         if not os.path.exists(spool_dir):
-            os.mkdir(spool_dir)
+            os.makedirs(spool_dir)
         self.share_local_folder(local_path=spool_dir, folder_type='spool')
         self.print_queue = printqueue.X2goPrintQueue(profile_name=self.profile_name,
                                                      session_name=self.session_info.name,
@@ -585,7 +588,7 @@ class X2goTerminalSessionSTDOUT(object):
 
         mimebox_dir = os.path.join(self.session_info.local_container, 'mimebox')
         if not os.path.exists(mimebox_dir):
-            os.mkdir(mimebox_dir)
+            os.makedirs(mimebox_dir)
         self.share_local_folder(local_path=mimebox_dir, folder_type='mimebox')
         self.mimebox_queue = mimebox.X2goMIMEboxQueue(profile_name=self.profile_name,
                                                       session_name=self.session_info.name,
@@ -689,63 +692,75 @@ class X2goTerminalSessionSTDOUT(object):
         _x2go_key_fname = '%s/%s/%s' % (os.path.dirname(self.session_info.remote_container), 'ssh', 'key.z%s' % self.session_info.agent_pid)
         _x2go_key_bundle = _tmp_io_object.getvalue()
 
-        self.control_session._x2go_sftp_write(_x2go_key_fname, _x2go_key_bundle)
+        # if there is another call to this method currently being processed, wait for that one to finish
+        while self._share_local_folder_busy:
+            gevent.sleep(.1)
+        self._share_local_folder_busy = True
 
-        _convert_encoding = self.params.convert_encoding
-        _client_encoding = self.params.client_encoding
-        _server_encoding = self.params.server_encoding
+        try:
+            self.control_session._x2go_sftp_write(_x2go_key_fname, _x2go_key_bundle)
 
-        if _X2GOCLIENT_OS == 'Windows':
-            local_path = local_path.replace('\\', '/')
-            local_path = local_path.replace(':', '')
-            local_path = '/windrive/%s' % local_path
-            _convert_encoding = True
-            _client_encoding = 'WINDOWS-1252'
+            _convert_encoding = self.params.convert_encoding
+            _client_encoding = self.params.client_encoding
+            _server_encoding = self.params.server_encoding
 
-        if _convert_encoding:
-            export_iconv_settings = 'export X2GO_ICONV=modules=iconv,from_code=%s,to_code=%s &&' % (_client_encoding, _server_encoding)
-        else:
-            export_iconv_settings = ''
-
-        if folder_type == 'disk':
-
-            cmd_line = [ '%s export HOSTNAME &&' % export_iconv_settings,
-                         'x2gomountdirs', 
-                         'dir',
-                         str(self.session_info.name), 
-                         '"%s"' % _CURRENT_LOCAL_USER,
-                         _x2go_key_fname,
-                         '%s__REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
-                         'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname),
-                       ]
-
-        elif folder_type == 'spool':
-
-            cmd_line = [ '%s export HOSTNAME &&' % export_iconv_settings,
-                         'x2gomountdirs', 
-                         'dir',
-                         str(self.session_info.name), 
-                         '"%s"' % _CURRENT_LOCAL_USER,
-                         _x2go_key_fname,
-                         '%s__PRINT_SPOOL___REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
-                         'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname), 
-                       ]
-
-        elif folder_type == 'mimebox':
-
-            cmd_line = [ '%s export HOSTNAME &&' % export_iconv_settings,
-                         'x2gomountdirs', 
-                         'dir',
-                         str(self.session_info.name), 
-                         '"%s"' % _CURRENT_LOCAL_USER,
-                         _x2go_key_fname,
-                         '%s__MIMEBOX_SPOOL___REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
-                         'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname), 
-                       ]
+            if _X2GOCLIENT_OS == 'Windows':
+                local_path = local_path.replace('\\', '/')
+                local_path = local_path.replace(':', '')
+                local_path = '/windrive/%s' % local_path
+                _convert_encoding = True
+                _client_encoding = 'WINDOWS-1252'
 
-        (stdin, stdout, stderr) = self.control_session._x2go_exec_command(cmd_line)
-        _stdout = stdout.read().split('\n')
-        self.logger('x2gomountdirs output is : %s' % _stdout, log.loglevel_NOTICE)
+            if _convert_encoding:
+                export_iconv_settings = 'export X2GO_ICONV=modules=iconv,from_code=%s,to_code=%s &&' % (_client_encoding, _server_encoding)
+            else:
+                export_iconv_settings = ''
+
+            if folder_type == 'disk':
+
+                cmd_line = [ '%s export HOSTNAME &&' % export_iconv_settings,
+                             'x2gomountdirs',
+                             'dir',
+                             str(self.session_info.name),
+                             '"%s"' % _CURRENT_LOCAL_USER,
+                             _x2go_key_fname,
+                             '%s__REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
+                             'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname),
+                           ]
+
+            elif folder_type == 'spool':
+
+                cmd_line = [ '%s export HOSTNAME &&' % export_iconv_settings,
+                             'x2gomountdirs',
+                             'dir',
+                             str(self.session_info.name),
+                             '"%s"' % _CURRENT_LOCAL_USER,
+                             _x2go_key_fname,
+                             '%s__PRINT_SPOOL___REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
+                             'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname), 
+                           ]
+
+            elif folder_type == 'mimebox':
+
+                cmd_line = [ '%s export HOSTNAME &&' % export_iconv_settings,
+                             'x2gomountdirs',
+                             'dir',
+                             str(self.session_info.name),
+                             '"%s"' % _CURRENT_LOCAL_USER,
+                             _x2go_key_fname,
+                             '%s__MIMEBOX_SPOOL___REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
+                             'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname), 
+                           ]
+
+            (stdin, stdout, stderr) = self.control_session._x2go_exec_command(cmd_line)
+            _stdout = stdout.read().split('\n')
+            self.logger('x2gomountdirs output is: %s' % _stdout, log.loglevel_NOTICE)
+
+        except:
+            raise
+        finally:
+            # allow sharing of other folders again
+            self._share_local_folder_busy = False
 
         if len(_stdout) >= 6 and _stdout[5].endswith('ok'):
             return True
@@ -1036,20 +1051,29 @@ class X2goTerminalSessionSTDOUT(object):
             return self.session_info.is_published_applications_provider()
         return False
 
-    def exec_published_application(self, exec_name, timeout=20):
+    def exec_published_application(self, exec_name, timeout=20, env={}):
         """\
         Executed a published application.
 
         @param exec_name: application to be executed
         @type exec_name: C{str}
+        @param timeout: execution timeout
+        @type timeout: C{int}
+        @param env: session environment dictionary
+        @type env: C{dict}
+
         """
         cmd_line = [
-            "export DISPLAY=:%s &&" % str(self.session_info.display),
-            "export X2GO_SESSION=%s &&" % str(self.get_session_name()),
+            "export DISPLAY=:%s && " % str(self.session_info.display),
+            "export X2GO_SESSION=%s && " % str(self.get_session_name()),
         ]
 
         if self.params.snd_system == 'pulse':
-            cmd_line.append("export PULSE_CLIENTCONFIG=%s/.pulse-client.conf &&" % self.session_info.remote_container)
+            cmd_line.append("export PULSE_CLIENTCONFIG=%s/.pulse-client.conf && " % self.session_info.remote_container)
+
+        if env:
+            for env_var in env.keys():
+                cmd_line = [ 'export %s=%s && ' % (env_var, env[env_var]) ] + cmd_line
 
         cmd_line.extend(
             [
@@ -1057,6 +1081,7 @@ class X2goTerminalSessionSTDOUT(object):
                 "&> /dev/null & exit",
             ]
         )
+
         self.logger('executing published application %s for %s with command line: %s' % (exec_name, self.profile_name, cmd_line), loglevel=log.loglevel_DEBUG)
         (stdin, stdout, stderr) = self.control_session._x2go_exec_command(cmd_line, timeout=timeout)
 
@@ -1121,8 +1146,8 @@ class X2goTerminalSessionSTDOUT(object):
             return False
 
         setkbd = "0"
-        if self.params.kblayout or self.params.kbtype:
-            setkbd = "1"
+        if (self.params.kblayout != "null") or (self.params.kbtype != "null/null"):
+            setkbd = "0"
 
         if '/' in self.params.cmd:
             self.params.cmd = os.path.basename(self.params.cmd)
@@ -1182,18 +1207,20 @@ class X2goTerminalSessionSTDOUT(object):
                                         session_instance=self.session_instance,
                                         proxy_options=self.proxy_options,
                                         logger=self.logger)
-        self.proxy_subprocess = self.proxy.start_proxy()
-        self.active_threads.append(self.proxy)
+        self.proxy_subprocess, proxy_ok = self.proxy.start_proxy()
 
-        if self.params.session_type in ('D', 'S'):
-            self.find_session_window()
-            self.auto_session_window_title()
-            self.raise_session_window()
+        if proxy_ok:
+            self.active_threads.append(self.proxy)
 
-        if self.params.published_applications:
-            self.control_session.get_published_applications()
+            if self.params.session_type in ('D', 'S'):
+                self.find_session_window()
+                self.auto_session_window_title()
+                self.raise_session_window()
 
-        return self.ok()
+            if self.params.published_applications:
+                self.control_session.get_published_applications()
+
+        return proxy_ok
 
     def resume(self):
         """\
@@ -1207,7 +1234,7 @@ class X2goTerminalSessionSTDOUT(object):
 
         """
         setkbd = "0"
-        if self.params.kblayout or self.params.kbtype:
+        if (self.params.kblayout != "null") or (self.params.kbtype != "null/null"):
             setkbd = "1"
 
         cmd_line = [ "x2goresume-session", self.session_info.name,
@@ -1253,28 +1280,29 @@ class X2goTerminalSessionSTDOUT(object):
                                         session_instance=self.session_instance,
                                         logger=self.logger
                                        )
-        self.proxy_subprocess = self.proxy.start_proxy()
-
-        # local path may be a Windows path, so we use the path separator of the local system
-        self.session_info.local_container = os.path.join(self.params.rootdir, 'S-%s' % self.session_info.name)
-        # remote path is always a UniX path...
-        self.session_info.remote_container = '%s/.x2go/C-%s' % (self.control_session._x2go_remote_home, 
-                                                                self.session_info.name,
-                                                               )
-        self.params.depth = self.session_info.name.split('_')[2][2:]
-        # on a session resume the user name comes in as a user ID. We have to translate this...
-        self.session_info.username = self.control_session.remote_username()
-
-        if self.params.session_type in ('D', 'S'):
-            self.find_session_window()
-            self.auto_session_window_title()
-            self.raise_session_window()
-
-        if self.is_published_applications_provider():
-            self.control_session.get_published_applications()
-            self.published_applications = True
-
-        return self.ok()
+        self.proxy_subprocess, proxy_ok = self.proxy.start_proxy()
+
+        if proxy_ok:
+            # local path may be a Windows path, so we use the path separator of the local system
+            self.session_info.local_container = os.path.join(self.params.rootdir, 'S-%s' % self.session_info.name)
+            # remote path is always a UniX path...
+            self.session_info.remote_container = '%s/.x2go/C-%s' % (self.control_session._x2go_remote_home, 
+                                                                    self.session_info.name,
+                                                                   )
+            self.params.depth = self.session_info.name.split('_')[2][2:]
+            # on a session resume the user name comes in as a user ID. We have to translate this...
+            self.session_info.username = self.control_session.remote_username()
+
+            if self.params.session_type in ('D', 'S'):
+                self.find_session_window()
+                self.auto_session_window_title()
+                self.raise_session_window()
+
+            if self.is_published_applications_provider():
+                self.control_session.get_published_applications()
+                self.published_applications = True
+
+        return proxy_ok
 
     def suspend(self):
         """\
diff --git a/x2go/client.py b/x2go/client.py
index 7e81e4b..5bbdb17 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -1480,9 +1480,9 @@ class X2goClient(object):
                 raise x2go_exceptions.X2goClientException('don\'t know which session to resume')
             if session_uuid is None:
                 session_uuid = self.session_registry.get_session_of_session_name(session_name=session_name, return_object=False)
-                return self.session_registry(session_uuid).resume()
+                return self.session_registry(session_uuid).resume(session_list=self.list_sessions(session_uuid=session_uuid))
             else:
-                return self.session_registry(session_uuid).resume(session_name=session_name)
+                return self.session_registry(session_uuid).resume(session_name=session_name, session_list=self.list_sessions(session_uuid=session_uuid))
         except x2go_exceptions.X2goControlSessionException:
             profile_name = self.get_session_profile_name(session_uuid)
             self.HOOK_on_control_session_death(profile_name)
diff --git a/x2go/forward.py b/x2go/forward.py
index dca0e70..b10e86f 100644
--- a/x2go/forward.py
+++ b/x2go/forward.py
@@ -72,6 +72,7 @@ class X2goFwServer(StreamServer):
 
         self.chan = None
         self.is_active = False
+        self.failed = False
         self.keepalive = False
         self.chain_host = remote_host
         self.chain_port = remote_port
@@ -124,26 +125,24 @@ class X2goFwServer(StreamServer):
                                                                                           loglevel=log.loglevel_WARN)
                 gevent.sleep(.4)
 
-
         if not _success:
             self.logger('incoming request to %s:%d failed after %d attempts' % (self.chain_host,
                                                                                 self.chain_port,
                                                                                 _count),
                                                                                 loglevel=log.loglevel_ERROR)
+            if self.session_instance:
+                self.session_instance.HOOK_forwarding_tunnel_setup_failed(chain_host=self.chain_host, chain_port=self.chain_port)
+            self.failed = True
+
         else:
+
+            self.logger('connected!  Tunnel open %r -> %r -> %r' % (self.fw_socket.getpeername(),
+                        chan_peername, (self.chain_host, self.chain_port)),
+                        loglevel=log.loglevel_INFO)
+
             # once we are here, we can presume the tunnel to be active...
             self.is_active = True
 
-            if self.chan is None:
-                self.logger('incoming request to [%s]:%d was rejected by the SSH server.' %
-                            (self.chain_host, self.chain_port), loglevel=log.loglevel_ERROR)
-                if self.session_instance:
-                    self.session_instance.HOOK_forwarding_tunnel_setup_failed(chain_host=self.chain_host, chain_port=self.chain_port)
-                return
-            else:
-                self.logger('connected!  Tunnel open %r -> %r -> %r' % (self.fw_socket.getpeername(),
-                                                                chan_peername, (self.chain_host, self.chain_port)),
-                                                                loglevel=log.loglevel_INFO)
             self.keepalive = True
             try:
                 while self.keepalive:
@@ -243,22 +242,19 @@ def start_forward_tunnel(local_host='127.0.0.1', local_port=22022,
     @rtype: C{instance}
 
     """
+    fw_server = X2goFwServer(listener=(local_host, local_port),
+                             remote_host=remote_host, remote_port=remote_port,
+                             ssh_transport=ssh_transport, session_instance=session_instance,
+                             logger=logger,
+                            )
     try:
-        fw_server = X2goFwServer(listener=(local_host, local_port),
-                                 remote_host=remote_host, remote_port=remote_port,
-                                 ssh_transport=ssh_transport, session_instance=session_instance,
-                                 logger=logger,
-                                )
-        try:
-            fw_server.start()
-            return fw_server
-        except socket.error:
-            pass
-    except x2go_exceptions.X2goFwTunnelException:
+        fw_server.start()
+    except socket.error:
+        fw_server.failed = True
+        fw_server.is_active = False
         pass
 
-    return None
-
+    return fw_server
 
 def stop_forward_tunnel(fw_server):
     """\
diff --git a/x2go/registry.py b/x2go/registry.py
index 54b9a16..0b25e4d 100644
--- a/x2go/registry.py
+++ b/x2go/registry.py
@@ -312,8 +312,8 @@ class X2goSessionRegistry(object):
 
                 # unregister as master session
                 if _profile_name in self.master_sessions.keys():
-                    self(_session_uuid).unset_master_session()
                     if self.master_sessions[_profile_name] == self(_session_uuid):
+                        self(_session_uuid).unset_master_session()
                         del self.master_sessions[_profile_name]
 
                 # session has been suspended
@@ -324,8 +324,8 @@ class X2goSessionRegistry(object):
 
                 # unregister as master session
                 if _profile_name in self.master_sessions.keys():
-                    self(_session_uuid).unset_master_session()
                     if self.master_sessions[_profile_name] == self(_session_uuid):
+                        self(_session_uuid).unset_master_session()
                         del self.master_sessions[_profile_name]
 
                 # session has terminated
diff --git a/x2go/session.py b/x2go/session.py
index 22f8ac9..35db50a 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -488,7 +488,7 @@ class X2goSession(object):
         """
         self.logger('Using session %s as master session for profile %s.' % (self.get_session_name(), self.get_profile_name()), loglevel=log.loglevel_NOTICE)
         self.master_session = True
-        self.share_all_local_folders()
+        gevent.spawn(self.share_all_local_folders)
 
     def unset_master_session(self):
         """\
@@ -866,7 +866,6 @@ class X2goSession(object):
         @return: returns C{True} if this L{X2goSession} has a terminal session associated to itself
         @rtype: C{bool}
 
-
         """
         return self.terminal_session not in (None, 'PENDING')
     __has_terminal_session = has_terminal_session
@@ -1374,7 +1373,7 @@ class X2goSession(object):
         """
         if self.terminal_session is not None:
             self.logger('for %s executing published application: %s' % (self.profile_name, exec_name), loglevel=log.loglevel_NOTICE)
-            self.terminal_session.exec_published_application(exec_name, timeout=timeout)
+            self.terminal_session.exec_published_application(exec_name, timeout=timeout, env=self.session_environment)
     __exec_published_application = exec_published_application
 
     def do_auto_start_or_resume(self, newest=True, oldest=False, all_suspended=False, start=True, redirect_to_client=True):
@@ -1423,7 +1422,7 @@ class X2goSession(object):
                     if not self.published_applications:
                         return self.start()
 
-    def resume(self, session_name=None):
+    def resume(self, session_name=None, session_list=None):
         """\
         Resume or continue a suspended / running X2Go session on the
         remote X2Go server.
@@ -1441,11 +1440,13 @@ class X2goSession(object):
             self.session_name = session_name
 
         if self.is_alive():
+
             _control = self.control_session
 
             # FIXME: normally this part gets called if you suspend a session that is associated to another client
             # we do not have a possibility to really check if SSH has released port forwarding channels or
             # sockets, thus  we plainly have to wait a while
+
             if self.is_running():
                 try:
                     self.suspend()
@@ -1462,6 +1463,7 @@ class X2goSession(object):
 
             self.terminal_session = _control.resume(session_name=self.session_name,
                                                     session_instance=self,
+                                                    session_list=session_list,
                                                     logger=self.logger, **self.terminal_params)
 
             if self.session_name is None:
@@ -1476,10 +1478,6 @@ class X2goSession(object):
 
                 self.terminal_session.session_info_protect()
 
-                # only run the session startup command if we do not resume...
-                if _new_session:
-                    self.has_terminal_session() and self.terminal_session.run_command(env=self.session_environment)
-
                 if self.get_session_cmd() != 'PUBLISHED':
                     self.published_applications = False
 
@@ -1500,24 +1498,27 @@ class X2goSession(object):
                     self._SUPPORTED_MIMEBOX = False
                     self._SUPPORTED_FOLDERSHARING = False
 
-                try:
-                    if self._SUPPORTED_PRINTING and self.printing:
-                        self.has_terminal_session() and not self.faulty and self.terminal_session.start_printing()
+                if self._SUPPORTED_PRINTING and self.printing:
+                    try:
+                        self.has_terminal_session() and not self.faulty and gevent.spawn(self.terminal_session.start_printing)
                         self.has_terminal_session() and not self.faulty and self.session_environment.update({'X2GO_SPOOLDIR': self.terminal_session.get_printing_spooldir(), })
-                except x2go_exceptions.X2goUserException, e:
-                    self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
-                    self.HOOK_printing_not_available()
-                    self._SUPPORTED_PRINTING = False
-
-                try:
-                    if self._SUPPORTED_MIMEBOX and self.allow_mimebox:
-                        self.has_terminal_session() and not self.faulty and self.terminal_session.start_mimebox(mimebox_extensions=self.mimebox_extensions, mimebox_action=self.mimebox_action)
+                    except x2go_exceptions.X2goUserException, e:
+                        self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
+                        self.HOOK_printing_not_available()
+                        self._SUPPORTED_PRINTING = False
+
+                if self._SUPPORTED_MIMEBOX and self.allow_mimebox:
+                    try:
+                        self.has_terminal_session() and not self.faulty and gevent.spawn(self.terminal_session.start_mimebox, mimebox_extensions=self.mimebox_extensions, mimebox_action=self.mimebox_action)
                         self.has_terminal_session() and self.session_environment.update({'X2GO_MIMEBOX': self.terminal_session.get_mimebox_spooldir(), })
-                except x2go_exceptions.X2goUserException, e:
-                    self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
-                    self.HOOK_mimebox_not_available()
-                    self._SUPPORTED_MIMEBOX = False
+                    except x2go_exceptions.X2goUserException, e:
+                        self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
+                        self.HOOK_mimebox_not_available()
+                        self._SUPPORTED_MIMEBOX = False
 
+                # only run the session startup command if we do not resume...
+                if _new_session:
+                    self.has_terminal_session() and self.terminal_session.run_command(env=self.session_environment)
 
                 self.virgin = False
                 self.suspended = False
@@ -1525,7 +1526,11 @@ class X2goSession(object):
                 self.terminated = False
                 self.faulty = False
 
-                self.share_all_local_folders()
+                # if there is a client instance for X2Go sessions that the client instance will handle the mounting of shared folders
+                if (not self.client_instance) and \
+                   self._SUPPORTED_FOLDERSHARING and \
+                   self.allow_share_local_folders:
+                    gevent.spawn(self.share_all_local_folders)
 
                 self.has_terminal_session() and self.terminal_session.session_info_unprotect()
                 return True
@@ -1916,7 +1921,7 @@ class X2goSession(object):
         """
         _retval = False
         if self.has_terminal_session() and self.share_local_folders and not self.faulty and self.is_running() and self.allow_share_local_folders:
-            if self._SUPPORTED_FOLDERSHARING and self.is_folder_sharing_available():
+            if self.is_folder_sharing_available() and self.is_master_session():
                 if self.control_session.get_transport().reverse_tunnels[self.terminal_session.get_session_name()]['sshfs'][1] is not None:
                     _retval = True
                     for _folder in self.share_local_folders:
diff --git a/x2go/sftpserver.py b/x2go/sftpserver.py
index 678f838..08243f7 100644
--- a/x2go/sftpserver.py
+++ b/x2go/sftpserver.py
@@ -493,6 +493,7 @@ class X2goRevFwTunnelToSFTP(rforward.X2goRevFwTunnel):
         @type loglevel: int
 
         """
+        self.ready = False
         if logger is None:
             self.logger = log.X2goLogger(loglevel=loglevel)
         else:
@@ -535,6 +536,7 @@ class X2goRevFwTunnelToSFTP(rforward.X2goRevFwTunnel):
         """
         self._request_port_forwarding()
         self._keepalive = True
+        self.ready = True
         while self._keepalive:
 
             self.incoming_channel.acquire()
@@ -560,6 +562,7 @@ class X2goRevFwTunnelToSFTP(rforward.X2goRevFwTunnel):
                                                              )
                 _new_chan_thread.start()
                 self.open_channels['[%s]:%s' % _chan.origin_addr] = _new_chan_thread
+        self.ready = False
 
 
 def x2go_rev_forward_sftpchannel_handler(chan=None, auth_key=None, logger=None):
diff --git a/x2go/sshproxy.py b/x2go/sshproxy.py
index 53dc8b9..7f28234 100644
--- a/x2go/sshproxy.py
+++ b/x2go/sshproxy.py
@@ -200,6 +200,7 @@ class X2goSSHProxy(paramiko.SSHClient, threading.Thread):
                                  look_for_keys=False,
                                  allow_agent=False,
                                 )
+
                 except x2go_exceptions.AuthenticationException, e:
                     self.close()
                     raise x2go_exceptions.X2goSSHProxyAuthenticationException('pubkey auth mechanisms both failed')
@@ -207,6 +208,11 @@ class X2goSSHProxy(paramiko.SSHClient, threading.Thread):
                     self.close()
                     raise
 
+                # since Paramiko 1.7.7.1 there is compression available, let's use it if present...
+                t = self.get_transport()
+                if hasattr(t, 'use_compression'):
+                    t.use_compression(compress=True)
+
             # if there is not private key, we will use the given password, if any
             else:
                 # create a random password if password is empty to trigger host key validity check
diff --git a/x2go/x2go_exceptions.py b/x2go/x2go_exceptions.py
index 1525359..a8eaa3f 100644
--- a/x2go/x2go_exceptions.py
+++ b/x2go/x2go_exceptions.py
@@ -58,6 +58,7 @@ class X2goRevFwTunnelException(_X2goException): pass
 class X2goPrintException(_X2goException): pass
 class X2goPrintQueueException(_X2goException): pass
 class X2goPrintActionException(_X2goException): pass
+class X2goProxyException(_X2goException): pass
 class X2goMIMEboxActionException(_X2goException): pass
 class X2goMIMEboxQueueException(_X2goException): pass
 class X2goSSHProxyException(_X2goException): pass


hooks/post-receive
-- 
python-x2go.git (Python X2Go Client API)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-x2go.git" (Python X2Go Client API).




More information about the x2go-commits mailing list