U
    ÓZjm ã                   @   s2  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	m	Z	 ddl
mZ ddlZejd dk rŽddlZddlZefZeZnddlZddlZeZeZdZdZdZd	Zd
Zdae ¡ ZdddddœZ ej!Z"dZ#e $e#d¡ dZ%ej&dkrþej'nej(Z)dZ%ej* +e%d¡Z,dd„ Z-dd„ Z.dd„ Z/dBdd„Z0dCdd„Z1dDdd „Z2dEd!d"„Z3d#d$„ Z4d%d&„ Z5d'd(„ Z6G d)d*„ d*e7ƒZ8G d+d,„ d,e8ƒZ9G d-d.„ d.ej:ƒZ;G d/d0„ d0ej(ƒZ<G d1d2„ d2ej=e<ƒZ>G d3d4„ d4e)ƒZ?G d5d6„ d6ej=e?ƒZ@G d7d8„ d8eAƒZBd9d:„ ZCd;d<„ ZDdFd=d>„ZEdGd?d@„ZFeGdAk�r.eFƒ  dS )Ha  
*sshtunnel* - Initiate SSH tunnels via a remote gateway.

``sshtunnel`` works by opening a port forwarding SSH connection in the
background, using threads.

The connection(s) are closed when explicitly calling the
:meth:`SSHTunnelForwarder.stop` method or using it as a context.

é    N)Úselect)Úhexlifyé   z0.4.0Zpahazçš™™™™™¹?g      $@Té   Ússh_address_or_hostÚssh_pkeyÚmute_exceptions)Ússh_addressÚssh_hostÚssh_private_keyÚ/raise_exception_if_any_forwarder_have_a_problemÚTRACEz~/.sshÚposixÚconfigc                 C   s"   t | tƒstd t| ƒj¡ƒ‚d S )NzIP is not a string ({0}))Ú
isinstanceÚstring_typesÚAssertionErrorÚformatÚtypeÚ__name__)Úhost© r   úL/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/sshtunnel.pyÚ
check_hostN   s    ÿr   c                 C   s,   t | tƒstdƒ‚| dks(td | ¡ƒ‚d S )NzPORT is not a numberr   zPORT < 0 ({0}))r   Úintr   r   )Úportr   r   r   Ú
check_portT   s    r   c                 C   sŠ   t | tƒr$t| d ƒ t| d ƒ nbt | tƒrrtjdkr@tdƒ‚tj 	| ¡s†t 
tj | ¡tj¡s†td | ¡ƒ‚ntd t| ƒj¡ƒ‚dS )aþ  
    Check if the format of the address is correct

    Arguments:
        address (tuple):
            (``str``, ``int``) representing an IP address and port,
            respectively

            .. note::
                alternatively a local ``address`` can be a ``str`` when working
                with UNIX domain sockets, if supported by the platform
    Raises:
        ValueError:
            raised when address has an incorrect format

    Example:
        >>> check_address(('127.0.0.1', 22))
    r   r   r   z-Platform does not support UNIX domain socketsz.ADDRESS not a valid socket domain socket ({0})z9ADDRESS is not a tuple, string, or character buffer ({0})N)r   Útupler   r   r   ÚosÚnameÚ
ValueErrorÚpathÚexistsÚaccessÚdirnameÚW_OKr   r   r   ©Úaddressr   r   r   Úcheck_addressY   s    


ÿÿÿr)   Fc                 C   sJ   t dd„ | D ƒƒst‚|r4tdd„ | D ƒƒr4tdƒ‚| D ]}t|ƒ q8dS )a  
    Check if the format of the addresses is correct

    Arguments:
        address_list (list[tuple]):
            Sequence of (``str``, ``int``) pairs, each representing an IP
            address and port respectively

            .. note::
                when supported by the platform, one or more of the elements in
                the list can be of type ``str``, representing a valid UNIX
                domain socket

        is_remote (boolean):
            Whether or not the address list
    Raises:
        AssertionError:
            raised when ``address_list`` contains an invalid element
        ValueError:
            raised when any address in the list has an incorrect format

    Example:

        >>> check_addresses([('127.0.0.1', 22), ('127.0.0.1', 2222)])
    c                 s   s   | ]}t |ttfƒV  qd S ©N)r   r   r   ©Ú.0Úxr   r   r   Ú	<genexpr>•   s     z"check_addresses.<locals>.<genexpr>c                 s   s   | ]}t |tƒV  qd S r*   )r   r   r+   r   r   r   r.   –   s     z3UNIX domain sockets not allowed for remoteaddressesN)Úallr   Úanyr)   )Zaddress_listÚ	is_remoter(   r   r   r   Úcheck_addresses{   s
    r2   c                 C   s°   | pt  d¡} tdd„ | jD ƒƒsJ|  |p,t¡ t  ¡ }t| ||pDtd� |rn|  |¡ | jD ]}| |¡ q^|r|t| d� |r¬t	j
dkr¬t  d¡ t  d¡}|j | j¡ | S )	a²  
    Attach or create a new logger and add a console handler if not present

    Arguments:

        logger (Optional[logging.Logger]):
            :class:`logging.Logger` instance; a new one is created if this
            argument is empty

        loglevel (Optional[str or int]):
            :class:`logging.Logger`'s level, either as a string (i.e.
            ``ERROR``) or in numeric format (10 == ``DEBUG``)

            .. note:: a value of 1 == ``TRACE`` enables Tracing mode

        capture_warnings (boolean):
            Enable/disable capturing the events logged by the warnings module
            into ``logger``'s handlers

            Default: True

            .. note:: ignored in python 2.6

        add_paramiko_handler (boolean):
            Whether or not add a console handler for ``paramiko.transport``'s
            logger if no handler present

            Default: True
    Return:
        :class:`logging.Logger`
    zsshtunnel.SSHTunnelForwarderc                 s   s   | ]}t |tjƒV  qd S r*   )r   ÚloggingÚHandlerr+   r   r   r   r.   Ä   s     z create_logger.<locals>.<genexpr>)ÚhandlerÚloglevel©Úlogger)é   é   Tzpy.warnings)r3   Ú	getLoggerr0   ÚhandlersÚsetLevelÚDEFAULT_LOGLEVELÚStreamHandlerÚ_add_handlerÚ_check_paramiko_handlersÚsysÚversion_infoÚcaptureWarningsÚextend)r8   r6   Zcapture_warningsZadd_paramiko_handlerÚconsole_handlerr5   Z
pywarningsr   r   r   Úcreate_loggerž   s*    #ÿþ




rG   c                 C   sN   |  |p
t¡ |jtjkr0d}| t |¡¡ n| t d¡¡ |  |¡ dS )z<
    Add a handler to an existing logging.Logger object
    z[%(asctime)s| %(levelname)-4.3s|%(threadName)10.9s/%(lineno)04d@%(module)-10.9s| %(message)sz)%(asctime)s| %(levelname)-8s| %(message)sN)r=   r>   Úlevelr3   ÚDEBUGÚsetFormatterÚ	FormatterÚ
addHandler)r8   r5   r6   Ú_fmtr   r   r   r@   Ù   s    ÿr@   c                 C   sD   t  d¡}|js@| r| j|_n"t  ¡ }| t  d¡¡ | |¡ dS )zN
    Add a console handler for paramiko.transport's logger if not present
    zparamiko.transportzP%(asctime)s | %(levelname)-8s| PARAMIKO: %(lineno)03d@%(module)-10s| %(message)sN)r3   r;   r<   r?   rJ   rK   rL   )r8   Zparamiko_loggerrF   r   r   r   rA   é   s    

ÿrA   c                 C   s   t | tƒrd | ¡S t| ƒS )Nz{0[0]}:{0[1]})r   r   r   Ústrr'   r   r   r   Úaddress_to_strú   s    

rO   c               	   C   s    t � t} td7 aW 5 Q R X | S ©Nr   )Ú_LOCKÚ_CONNECTION_COUNTER)Úuidr   r   r   Úget_connection_id   s    rT   c                    s   t tˆ j‡ fdd„ˆ D ƒƒƒS )z, Remove dictionary keys whose value is None c                    s   g | ]}ˆ | d kr|‘qS r*   r   )r,   Úi©Ú
dictionaryr   r   Ú
<listcomp>  s      z'_remove_none_values.<locals>.<listcomp>)ÚlistÚmapÚpoprV   r   rV   r   Ú_remove_none_values  s    ÿr\   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚBaseSSHTunnelForwarderErrorz8 Exception raised by :class:`SSHTunnelForwarder` errors c                 O   s   |  d|r|d nd¡| _d S )NÚvaluer   Ú )r[   r^   ©ÚselfÚargsÚkwargsr   r   r   Ú__init__  s    z$BaseSSHTunnelForwarderError.__init__c                 C   s   | j S r*   )r^   ©ra   r   r   r   Ú__str__  s    z#BaseSSHTunnelForwarderError.__str__N)r   Ú
__module__Ú__qualname__Ú__doc__rd   rf   r   r   r   r   r]     s   r]   c                   @   s   e Zd ZdZdS )ÚHandlerSSHTunnelForwarderErrorz' Exception for Tunnel forwarder errors N)r   rg   rh   ri   r   r   r   r   rj     s   rj   c                   @   s0   e Zd ZdZdZdZdZdZdd„ Zdd„ Z	dS )Ú_ForwardHandlerz% Base handler for tunnel connections Nc              	   C   sÜ   |j rØt| j|gg g dƒ\}}}| j|kr|| j d¡}|sR| j td | j¡¡ qØ| j td | j| j	t
|ƒ¡¡ | |¡ ||kr | ¡ s¤| j td | j¡¡ qØ| d¡}| j td | jt
|ƒ¡¡ | j |¡ q d S )Né   i   z>>> OUT {0} recv empty data >>>z >>> OUT {0} send to {1}: {2} >>>z <<< IN {0} recv is not ready <<<z<<< IN {0} recv: {1} <<<)Zactiver   ÚrequestÚrecvr8   ÚlogÚTRACE_LEVELr   ÚinfoÚremote_addressr   ÚsendallZ
recv_ready)ra   ÚchanZrqstÚ_Údatar   r   r   Ú	_redirect1  s@    

þýþ

þ
þz_ForwardHandler._redirectc                 C   s~  t ƒ }d || jp| jj¡| _| j ¡ }t|t	ƒs6d}z| j
jd| j|td�}W nf tk
r¶ } zHt|tjƒrrdnd}d ||¡}d | j|¡}| j t|¡ t|ƒ‚W 5 d }~X Y nX | j td	 | j¡¡ z€z|  |¡ W nl tjk
�r   | j td | j¡¡ Y n@ tk
�rJ } z | j td | jt|ƒ¡¡ W 5 d }~X Y nX W 5 | ¡  | j ¡  | j td
 | j¡¡ X d S )Nz#{0} <-- {1})Údummyi90  zdirect-tcpip)ÚkindZ	dest_addrZsrc_addrÚtimeoutzssh r_   zopen new channel {0}error: {1}z{0} {1}z{0} connectedz{0} connection closed.z{0} sending RSTz{0} error: {1})rT   r   Úclient_addressÚserverÚlocal_addressrq   rm   Úgetpeernamer   r   Ússh_transportZopen_channelrr   ÚTUNNEL_TIMEOUTÚ	ExceptionÚparamikoÚSSHExceptionr8   ro   rp   rj   Úcloserw   ÚsocketÚerrorÚrepr)ra   rS   Zsrc_addressrt   ÚeZmsg_tupeZexc_msgZlog_msgr   r   r   ÚhandleS  sD    ÿ

ü
ÿ

ÿz_ForwardHandler.handle)
r   rg   rh   ri   rr   r   r8   rq   rw   r‰   r   r   r   r   rk   *  s   "rk   c                   @   sl   e Zd ZdZdZdd„ Zdd„ Zedd„ ƒZed	d
„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZdS )Ú_ForwardServerz5
    Non-threading version of the forward server
    Tc                 O   s6   t | dd ¡ƒ| _t d¡| _tjj| f|ž|Ž d S ©Nr8   r   )	rG   r[   r8   ÚqueueÚQueueÚ	tunnel_okÚsocketserverÚ	TCPServerrd   r`   r   r   r   rd   �  s    z_ForwardServer.__init__c                 C   sˆ   t  ¡ \}}}| ¡ }| j}| j d |||¡¡ z| jjdddd� W n: t	j
k
r^   Y n& |k
r‚   | j d |¡¡ Y nX d S )NzSCould not establish connection from local {0} to remote {1} side of the tunnel: {2}Fr   )Úblockrz   zunexpected internal error: {0})rB   Úexc_infoÚgetsocknamerr   r8   r†   r   rŽ   ÚputrŒ   ÚFull)ra   rm   r{   Ú	exc_classÚexcÚtbZ
local_sideZremote_sider   r   r   Úhandle_error†  s    
  þz_ForwardServer.handle_errorc                 C   s   | j S r*   ©Úserver_addressre   r   r   r   r}   •  s    z_ForwardServer.local_addressc                 C   s
   | j d S ©Nr   rš   re   r   r   r   Ú
local_host™  s    z_ForwardServer.local_hostc                 C   s
   | j d S rP   rš   re   r   r   r   Ú
local_port�  s    z_ForwardServer.local_portc                 C   s   | j jS r*   ©ÚRequestHandlerClassrr   re   r   r   r   rr   ¡  s    z_ForwardServer.remote_addressc                 C   s   | j jd S rœ   rŸ   re   r   r   r   Úremote_host¥  s    z_ForwardServer.remote_hostc                 C   s   | j jd S rP   rŸ   re   r   r   r   Úremote_port©  s    z_ForwardServer.remote_portN)r   rg   rh   ri   Úallow_reuse_addressrd   r™   Úpropertyr}   r�   rž   rr   r¡   r¢   r   r   r   r   rŠ   {  s    




rŠ   c                   @   s   e Zd ZdZeZdS )Ú_ThreadingForwardServerú5
    Allow concurrent connections to each tunnel
    N©r   rg   rh   ri   Ú_DAEMONÚdaemon_threadsr   r   r   r   r¥   ®  s   r¥   c                   @   s`   e Zd ZdZdd„ Zedd„ ƒZedd„ ƒZedd	„ ƒZed
d„ ƒZ	edd„ ƒZ
edd„ ƒZdS )Ú_StreamForwardServerz>
    Serve over domain sockets (does not work on Windows)
    c                 O   s4   t | dd ¡ƒ| _t d¡| _tj| f|ž|Ž d S r‹   )rG   r[   r8   rŒ   r�   rŽ   Ú_StreamServerrd   r`   r   r   r   rd   ¼  s    z_StreamForwardServer.__init__c                 C   s   | j S r*   rš   re   r   r   r   r}   Á  s    z"_StreamForwardServer.local_addressc                 C   s   d S r*   r   re   r   r   r   r�   Å  s    z_StreamForwardServer.local_hostc                 C   s   d S r*   r   re   r   r   r   rž   É  s    z_StreamForwardServer.local_portc                 C   s   | j jS r*   rŸ   re   r   r   r   rr   Í  s    z#_StreamForwardServer.remote_addressc                 C   s   | j jd S rœ   rŸ   re   r   r   r   r¡   Ñ  s    z _StreamForwardServer.remote_hostc                 C   s   | j jd S rP   rŸ   re   r   r   r   r¢   Õ  s    z _StreamForwardServer.remote_portN)r   rg   rh   ri   rd   r¤   r}   r�   rž   rr   r¡   r¢   r   r   r   r   rª   ·  s   




rª   c                   @   s   e Zd ZdZeZdS )Ú_ThreadingStreamForwardServerr¦   Nr§   r   r   r   r   r¬   Ú  s   r¬   c                   @   sÞ  e Zd ZdZdZeZeZdd„ Zdd„ Z	dd„ Z
d	d
„ Zdd„ Zdd„ Zdd„ Zdeddddddddddddddddddfdd„ZedWdd„ƒZedXdd„ƒZedYdd„ƒZedd„ ƒZedZdd„ƒZedfd d!„Zd"d#„ Zd$d%„ Zed[d&d'„ƒZed(d)„ ƒZed\d*d+„ƒZd,d-„ Zd]d.d/„Zd0d1„ Z d2d3„ Z!d4d5„ Z"d^d7d8„Z#d_d9d:„Z$e%d;d<„ ƒZ&e%d=d>„ ƒZ'e%d?d@„ ƒZ(e%dAdB„ ƒZ)e%dCdD„ ƒZ*e%dEdF„ ƒZ+e%dGdH„ ƒZ,e%dIdJ„ ƒZ-dKdL„ Z.dMdN„ Z/dOdP„ Z0dQdR„ Z1dSdT„ Z2dUdV„ Z3dS )`ÚSSHTunnelForwardera	#  
    **SSH tunnel class**

        - Initialize a SSH tunnel to a remote host according to the input
          arguments

        - Optionally:
            + Read an SSH configuration file (typically ``~/.ssh/config``)
            + Load keys from a running SSH agent (i.e. Pageant, GNOME Keyring)

    Raises:

        :class:`.BaseSSHTunnelForwarderError`:
            raised by SSHTunnelForwarder class methods

        :class:`.HandlerSSHTunnelForwarderError`:
            raised by tunnel forwarder threads

            .. note::
                    Attributes ``mute_exceptions`` and
                    ``raise_exception_if_any_forwarder_have_a_problem``
                    (deprecated) may be used to silence most exceptions raised
                    from this class

    Keyword Arguments:

        ssh_address_or_host (tuple or str):
            IP or hostname of ``REMOTE GATEWAY``. It may be a two-element
            tuple (``str``, ``int``) representing IP and port respectively,
            or a ``str`` representing the IP address only

            .. versionadded:: 0.0.4

        ssh_config_file (str):
            SSH configuration file that will be read. If explicitly set to
            ``None``, parsing of this configuration is omitted

            Default: :const:`SSH_CONFIG_FILE`

            .. versionadded:: 0.0.4

        ssh_host_key (str):
            Representation of a line in an OpenSSH-style "known hosts"
            file.

            ``REMOTE GATEWAY``'s key fingerprint will be compared to this
            host key in order to prevent against SSH server spoofing.
            Important when using passwords in order not to accidentally
            do a login attempt to a wrong (perhaps an attacker's) machine

        ssh_username (str):
            Username to authenticate as in ``REMOTE SERVER``

            Default: current local user name

        ssh_password (str):
            Text representing the password used to connect to ``REMOTE
            SERVER`` or for unlocking a private key.

            .. note::
                Avoid coding secret password directly in the code, since this
                may be visible and make your service vulnerable to attacks

        ssh_port (int):
            Optional port number of the SSH service on ``REMOTE GATEWAY``,
            when `ssh_address_or_host`` is a ``str`` representing the
            IP part of ``REMOTE GATEWAY``'s address

            Default: 22

        ssh_pkey (str or paramiko.PKey):
            **Private** key file name (``str``) to obtain the public key
            from or a **public** key (:class:`paramiko.pkey.PKey`)

        ssh_private_key_password (str):
            Password for an encrypted ``ssh_pkey``

            .. note::
                Avoid coding secret password directly in the code, since this
                may be visible and make your service vulnerable to attacks

        ssh_proxy (socket-like object or tuple):
            Proxy where all SSH traffic will be passed through.
            It might be for example a :class:`paramiko.proxy.ProxyCommand`
            instance.
            See either the :class:`paramiko.transport.Transport`'s sock
            parameter documentation or ``ProxyCommand`` in ``ssh_config(5)``
            for more information.

            It is also possible to specify the proxy address as a tuple of
            type (``str``, ``int``) representing proxy's IP and port

            .. note::
                Ignored if ``ssh_proxy_enabled`` is False

            .. versionadded:: 0.0.5

        ssh_proxy_enabled (boolean):
            Enable/disable SSH proxy. If True and user's
            ``ssh_config_file`` contains a ``ProxyCommand`` directive
            that matches the specified ``ssh_address_or_host``,
            a :class:`paramiko.proxy.ProxyCommand` object will be created where
            all SSH traffic will be passed through

            Default: ``True``

            .. versionadded:: 0.0.4

        local_bind_address (tuple):
            Local tuple in the format (``str``, ``int``) representing the
            IP and port of the local side of the tunnel. Both elements in
            the tuple are optional so both ``('', 8000)`` and
            ``('10.0.0.1', )`` are valid values

            Default: ``('0.0.0.0', RANDOM_PORT)``

            .. versionchanged:: 0.0.8
                Added the ability to use a UNIX domain socket as local bind
                address

        local_bind_addresses (list[tuple]):
            In case more than one tunnel is established at once, a list
            of tuples (in the same format as ``local_bind_address``)
            can be specified, such as [(ip1, port_1), (ip_2, port2), ...]

            Default: ``[local_bind_address]``

            .. versionadded:: 0.0.4

        remote_bind_address (tuple):
            Remote tuple in the format (``str``, ``int``) representing the
            IP and port of the remote side of the tunnel.

        remote_bind_addresses (list[tuple]):
            In case more than one tunnel is established at once, a list
            of tuples (in the same format as ``remote_bind_address``)
            can be specified, such as [(ip1, port_1), (ip_2, port2), ...]

            Default: ``[remote_bind_address]``

            .. versionadded:: 0.0.4

        allow_agent (boolean):
            Enable/disable load of keys from an SSH agent

            Default: ``True``

            .. versionadded:: 0.0.8

        host_pkey_directories (list):
            Look for pkeys in folders on this list, for example ['~/.ssh'].

            Default: ``None`` (disabled)

            .. versionadded:: 0.1.4

        compression (boolean):
            Turn on/off transport compression. By default compression is
            disabled since it may negatively affect interactive sessions

            Default: ``False``

            .. versionadded:: 0.0.8

        logger (logging.Logger):
            logging instance for sshtunnel and paramiko

            Default: :class:`logging.Logger` instance with a single
            :class:`logging.StreamHandler` handler and
            :const:`DEFAULT_LOGLEVEL` level

            .. versionadded:: 0.0.3

        mute_exceptions (boolean):
            Allow silencing :class:`BaseSSHTunnelForwarderError` or
            :class:`HandlerSSHTunnelForwarderError` exceptions when enabled

            Default: ``False``

            .. versionadded:: 0.0.8

        set_keepalive (float):
            Interval in seconds defining the period in which, if no data
            was sent over the connection, a *'keepalive'* packet will be
            sent (and ignored by the remote host). This can be useful to
            keep connections alive over a NAT. You can set to 0.0 for
            disable keepalive.

            Default: 5.0 (no keepalive packets are sent)

            .. versionadded:: 0.0.7

        threaded (boolean):
            Allow concurrent connections over a single tunnel

            Default: ``True``

            .. versionadded:: 0.0.3

        ssh_address (str):
            Superseded by ``ssh_address_or_host``, tuple of type (str, int)
            representing the IP and port of ``REMOTE SERVER``

            .. deprecated:: 0.0.4

        ssh_host (str):
            Superseded by ``ssh_address_or_host``, tuple of type
            (str, int) representing the IP and port of ``REMOTE SERVER``

            .. deprecated:: 0.0.4

        ssh_private_key (str or paramiko.PKey):
            Superseded by ``ssh_pkey``, which can represent either a
            **private** key file name (``str``) or a **public** key
            (:class:`paramiko.pkey.PKey`)

            .. deprecated:: 0.0.8

        raise_exception_if_any_forwarder_have_a_problem (boolean):
            Allow silencing :class:`BaseSSHTunnelForwarderError` or
            :class:`HandlerSSHTunnelForwarderError` exceptions when set to
            False

            Default: ``True``

            .. versionadded:: 0.0.4

            .. deprecated:: 0.0.8 (use ``mute_exceptions`` instead)

    Attributes:

        tunnel_is_up (dict):
            Describe whether or not the other side of the tunnel was reported
            to be up (and we must close it) or not (skip shutting down that
            tunnel)

            .. note::
                This attribute should not be modified

            .. note::
                When :attr:`.skip_tunnel_checkup` is disabled or the local bind
                is a UNIX socket, the value will always be ``True``

            **Example**::

                {('127.0.0.1', 55550): True,   # this tunnel is up
                 ('127.0.0.1', 55551): False}  # this one isn't

            where 55550 and 55551 are the local bind ports

        skip_tunnel_checkup (boolean):
            Disable tunnel checkup (default for backwards compatibility).

            .. versionadded:: 0.1.0

    Tc                 C   sF   zt |ƒ W n" tk
r.   | j d¡ Y dS X |  ¡  | j |d¡S )a“  
        Check if a tunnel is up (remote target's host is reachable on TCP
        target's port)

        Arguments:
            target (tuple):
                tuple of type (``str``, ``int``) indicating the listen IP
                address and port
        Return:
            boolean

        .. deprecated:: 0.1.0
            Replaced by :meth:`.check_tunnels()` and :attr:`.tunnel_is_up`
        z©Target must be a tuple (IP, port), where IP is a string (i.e. "192.168.0.1") and port is an integer (i.e. 40000). Alternatively target can be a valid UNIX domain socket.FT)r)   r!   r8   ÚwarningÚcheck_tunnelsÚtunnel_is_upÚget)ra   Útargetr   r   r   Úlocal_is_upë  s    zSSHTunnelForwarder.local_is_upc                 C   s4   | j }z d| _ | jD ]}|  |¡ qW 5 || _ X dS )zg
        Check that if all tunnels are established and populates
        :attr:`.tunnel_is_up`
        FN)Úskip_tunnel_checkupÚ_server_listÚ_check_tunnel)ra   r´   Ú_srvr   r   r   r¯     s    
z SSHTunnelForwarder.check_tunnelsc                 C   s:  | j rd| j|j< dS | j d |j¡¡ t|jtƒrHt	 	t	j
t	j¡}nt	 	t	jt	j¡}| t¡ zÈzV|jdkrzd|jfn|j}| |¡ |jjtd d�| j|j< | j d |j¡¡ W nl t	jk
rð   | j d |j¡¡ d	| j|j< Y n8 tjk
�r&   | j d
 |j¡¡ d| j|j< Y nX W 5 | ¡  X dS )z( Check if tunnel is already established TNzChecking tunnel to: {0}ú0.0.0.0z	127.0.0.1gš™™™™™ñ?)rz   zTunnel to {0} is DOWNFzTunnel to {0} is UP)r´   r°   r}   r8   rq   r   rr   r   r   r…   ÚAF_UNIXÚSOCK_STREAMÚAF_INETÚ
settimeoutr€   r„   r�   rž   ÚconnectrŽ   r±   Údebugr†   rŒ   ÚEmpty)ra   r·   ÚsZ
connect_tor   r   r   r¶     s>    
ÿÿ
ÿ
ÿ
ÿ
ÿz SSHTunnelForwarder._check_tunnelc                    s   G ‡ ‡fdd„dt ƒ}|S )z(
        Make SSH Handler class
        c                       s   e Zd Z” Z”jZ”jZdS )zCSSHTunnelForwarder._make_ssh_forward_handler_class.<locals>.HandlerN)r   rg   rh   rr   Ú
_transportr   r8   r   ©Úremote_address_ra   r   r   r4   <  s   r4   )rk   )ra   rÃ   r4   r   rÂ   r   Ú_make_ssh_forward_handler_class8  s    z2SSHTunnelForwarder._make_ssh_forward_handler_classc                 C   s   | j r
tS tS r*   )Ú	_threadedr¥   rŠ   ©ra   rÃ   r   r   r   Ú_make_ssh_forward_server_classB  s    z1SSHTunnelForwarder._make_ssh_forward_server_classc                 C   s   | j r
tS tS r*   )rÅ   r¬   rª   rÆ   r   r   r   Ú%_make_stream_ssh_forward_server_classE  s    
ÿz8SSHTunnelForwarder._make_stream_ssh_forward_server_classc                 C   s´   |   |¡}ztt|tƒr| jn| j}||ƒ}|||| jd�}|r`| j|_| j 	|¡ d| j
|j< n|  td t|ƒt|ƒ¡¡ W n0 tk
r®   |  td t|ƒt|ƒ¡¡ Y nX dS )z5
        Make SSH forward proxy Server class
        r7   FzsProblem setting up ssh {0} <> {1} forwarder. You can suppress this exception by using the `mute_exceptions`argumentzLCouldn't open tunnel {0} <> {1} might be in use or destination not reachableN)rÄ   r   r   rÈ   rÇ   r8   Údaemon_forward_serversr©   rµ   Úappendr°   r›   Ú_raiser]   r   rO   ÚIOError)ra   rr   Úlocal_bind_addressZ_HandlerZforward_maker_classZ_ServerZssh_forward_serverr   r   r   Ú_make_ssh_forward_serverI  s>    
ÿþýýþýþz+SSHTunnelForwarder._make_ssh_forward_serverNFg      @c              
   O   s†  |pt ƒ | _t|d� || _|| _g | _i | _|| _d| _dD ]}|  	|||¡}q>|  	|d|¡}|  	d d|¡pr| | _
t|tƒr’t|ƒ |\}}n|}| dd ¡}|r´td |¡ƒ‚| j||dd	�| _|  |
|¡| _|  | j| j¡| _|  |||	|||rü|nd || j¡\| _| _}| _| _| _| j|||||| jd
�\| _| _t| jƒ t| jƒ | j  d | j| j| j¡¡ | j !d | j¡¡ d S )Nr7   F©r
   r   r   r   Ússh_portzUnknown arguments: {0}T)r1   )Ússh_passwordr   Ússh_pkey_passwordÚallow_agentÚhost_pkey_directoriesr8   z,Connecting to gateway: {0}:{1} as user '{2}'z#Concurrent connections allowed: {0})"rG   r8   rA   Ússh_host_keyÚset_keepaliverµ   r°   rÅ   Úis_aliveÚ_process_deprecatedÚ_raise_fwd_excr   r   r)   r[   r!   r   Ú
_get_bindsÚ_remote_bindsÚ_local_bindsÚ_consolidate_bindsÚ_read_ssh_configr   Ússh_usernamerÐ   Ú	ssh_proxyÚcompressionÚ_consolidate_authrÑ   Ú	ssh_pkeysr   r   rq   r¾   )ra   r   Ússh_config_filerÕ   rÑ   r   Ússh_private_key_passwordrà   Zssh_proxy_enabledrß   rÍ   Úlocal_bind_addressesr8   r	   Zremote_bind_addressÚremote_bind_addressesrÖ   Zthreadedrá   rÓ   rÔ   rb   rc   Údeprecated_argumentr   rÐ   r   r   r   rd   o  s–    
þþýý

þÿÿ
øûú	


ý
ÿzSSHTunnelForwarder.__init__c                 C   sX  t  ¡ }|sd}d�zzºttj |¡dƒ�}	| 	|	¡ W 5 Q R X | 
| ¡}
|pV|
 d¡}|pl|
 ddg¡d }|
 d¡} |p„|
 d¡}|
 d	¡}|p¤|r¢t  |¡nd}|dkrÎ|
 d
d¡}| ¡ dkrÊdnd}W nP tk
rø   |rô| d |¡¡ Y n* ttfk
�r    |�r| d¡ Y nX W 5 | |�p4t ¡ ||�rDt|ƒnd||f£  S X  )z¼
        Read ssh_config_file and tries to look for user (ssh_username),
        identityfile (ssh_pkey), port (ssh_port) and proxycommand
        (ssh_proxy) entries for ssh_host
        Né   ÚrÚuserZidentityfiler   Úhostnamer   Úproxycommandrá   r_   ZYESTFz*Could not read SSH configuration file: {0}z*Skipping loading of ssh configuration file)r‚   Z	SSHConfigÚgetpassÚgetuserr   Úopenr   r"   Ú
expanduserÚparseÚlookupr±   ÚProxyCommandÚupperrÌ   r®   r   ÚAttributeErrorÚ	TypeErrorrq   )r   rä   rß   r   rÐ   rà   rá   r8   Z
ssh_configÚfZhostname_inforí   r   r   r   rÞ   Ú  sR    
þþ

ÿÿÿÿûz#SSHTunnelForwarder._read_ssh_configc                 C   s0   t  ¡ }| ¡ }| r(|  d t|ƒ¡¡ t|ƒS )z› Load public keys from any available SSH agent

        Arguments:
            logger (Optional[logging.Logger])

        Return:
            list
        z{0} keys loaded from agent)r‚   ZAgentÚget_keysrq   r   ÚlenrY   )r8   Zparamiko_agentZ
agent_keysr   r   r   Úget_agent_keys  s
    
z!SSHTunnelForwarder.get_agent_keysc           
      C   s  |rt j| d�ng }|dkr"tg}tjtjtjdœ}ttdƒrHtj|d< |D ]š}| 	¡ D ]Œ}t
j t
j |d |¡¡¡}z2t
j |¡r¨t j|| || d�}|r¨| |¡ W qX tk
râ }	 z| rÒ|  d ||	¡¡ W 5 d}	~	X Y qXX qXqL| �r|  d	 t|ƒ¡¡ |S )
a3  
        Load public keys from any available SSH agent or local
        .ssh directory.

        Arguments:
            logger (Optional[logging.Logger])

            host_pkey_directories (Optional[list[str]]):
                List of local directories where host SSH pkeys in the format
                "id_*" are searched. For example, ['~/.ssh']

                .. versionadded:: 0.1.0

            allow_agent (Optional[boolean]):
                Whether or not load keys from agent

                Default: False

        Return:
            list
        r7   N)ÚrsaZdsaZecdsaÚ
Ed25519KeyZed25519zid_{})Ú	pkey_filer8   Úkey_typez%Private key file {0} check error: {1}z{0} key(s) loaded)r­   rû   ÚDEFAULT_SSH_DIRECTORYr‚   ÚRSAKeyÚDSSKeyÚECDSAKeyÚhasattrrý   Úkeysr   r"   rñ   Újoinr   ÚisfileÚread_private_key_filerÊ   ÚOSErrorr®   rq   rú   )
r8   rÔ   rÓ   r  Zparamiko_key_typesÚ	directoryZkeytypeÚssh_pkey_expandedr   r—   r   r   r   rù   '  sF    ÿÿþ

ÿý ÿzSSHTunnelForwarder.get_keysc                 C   s<   t |ƒt | ƒ }|dk r tdƒ‚|  dd„ t|ƒD ƒ¡ | S )zŸ
        Fill local_binds with defaults when no value/s were specified,
        leaving paramiko to decide in which local port the tunnel will be open
        r   zLToo many local bind addresses (local_bind_addresses > remote_bind_addresses)c                 S   s   g | ]}d ‘qS ))r¸   r   r   r+   r   r   r   rX   j  s     z9SSHTunnelForwarder._consolidate_binds.<locals>.<listcomp>)rú   r!   rE   Úrange)Zlocal_bindsZremote_bindsÚcountr   r   r   rÝ   `  s
    z%SSHTunnelForwarder._consolidate_bindsc                 C   sŽ   t j|||d�}t|tƒr\tj |¡}tj |¡rHt j||p>| |d�}n|r\| 	d 
|¡¡ t|tjjƒrv| d|¡ | s†|s†tdƒ‚| |fS )a2  
        Get sure authentication information is in place.
        ``ssh_pkey`` may be of classes:
            - ``str`` - in this case it represents a private key file; public
            key will be obtained from it
            - ``paramiko.Pkey`` - it will be transparently added to loaded keys

        )r8   rÔ   rÓ   )rþ   Úpkey_passwordr8   zPrivate key file not found: {0}r   z$No password or public key available!)r­   rù   r   r   r   r"   rñ   r#   r  r®   r   r‚   ÚpkeyZPKeyÚinsertr!   )rÑ   r   rÒ   rÓ   rÔ   r8   Zssh_loaded_pkeysr  r   r   r   râ   m  s,    ý
ýÿz$SSHTunnelForwarder._consolidate_authc                 C   s(   | j r||ƒ‚n| j t||ƒƒ¡ d S r*   )rÙ   r8   r†   r‡   )ra   Ú	exceptionÚreasonr   r   r   rË   ”  s    
zSSHTunnelForwarder._raisec                 C   s
  | j rLt| j tjjƒr(t| j jd ƒ}n
t| j ƒ}| j d 	|¡¡ | j }n| j
| jf}t|tjƒr€| t¡ | | j
| jf¡ t |¡}|j}t|tjƒr¦| t¡ | | j¡ |j| jd� | j|_t|tjƒ�r| ¡ }t|j|j|jfƒ}| j d 	||¡¡ |S )z0 Return the SSH transport to the remote gateway r   zConnecting via proxy: {0})Úcompressz'Transport socket info: {0}, timeout={1})rà   r   r‚   Úproxyrô   r‡   Úcmdr8   r¾   r   r   rÐ   r…   r¼   ÚSSH_TIMEOUTr½   Ú	TransportÚsockrÖ   Zuse_compressionrá   Údaemon_transportÚdaemonÚ
gettimeoutÚfamilyr   Úproto)ra   Z
proxy_reprÚ_socketÚ	transportr  Úsock_timeoutZ	sock_infor   r   r   Ú_get_transportš  s2    




 ÿz!SSHTunnelForwarder._get_transportc                 C   s  | j sšz|  ¡  W n† tjk
rB   d | j¡}| j |¡ Y dS  tj	tjfk
r˜ } z2d}| | j| j
|jd ¡}| j |¡ W Y ¢dS d}~X Y nX t| j| jƒD ]V\}}z|  ||¡ W q¨ tk
� rü } zd |j¡}| j |¡ W 5 d}~X Y q¨X q¨dS )zP
        Create SSH tunnels on top of a transport to the remote gateway
        z/Could not resolve IP address for {0}, aborting!Nz*Could not connect to gateway {0}:{1} : {2}r   z%Problem setting SSH Forwarder up: {0})Ú	is_activeÚ_connect_to_gatewayr…   Úgaierrorr   r   r8   r†   r‚   rƒ   rÐ   rb   ÚziprÛ   rÜ   rÎ   r]   r^   )ra   Úmsgrˆ   ÚtemplateÚremÚlocr   r   r   Ú_create_tunnels¸  s(    ÿz"SSHTunnelForwarder._create_tunnelsc                 C   s˜   |rdnd}| s.|s.|r(t d |¡ƒ‚qDg S n| rD|rDt d |¡ƒ‚| rN| g}|sŠt|ƒD ].\}}t|tƒrZt|ƒdkrZ|d df||< qZt||ƒ |S )NÚremoteÚlocalzXNo {0} bind addresses specified. Use '{0}_bind_address' or '{0}_bind_addresses' argumentzZYou can't use both '{0}_bind_address' and '{0}_bind_addresses' arguments. Use one of them.r   r   )r!   r   Ú	enumerater   r   rú   r2   )Zbind_addressZbind_addressesr1   Z	addr_kindrU   Z
local_bindr   r   r   rÚ   Ð  s&    þþ
zSSHTunnelForwarder._get_bindsc                 C   s^   |t krtd |¡ƒ‚||krZt d |t | ¡t¡ | rPtd |t | ¡ƒ‚n
| |¡S | S )z8
        Processes optional deprecate arguments
        z%{0} not included in deprecations listz%'{0}' is DEPRECATED use '{1}' insteadz?You can't use both '{0}' and '{1}'. Please only use one of them)Ú_DEPRECATIONSr!   r   ÚwarningsÚwarnÚDeprecationWarningr[   )ZattribZdeprecated_attribrc   r   r   r   rØ   é  s$    ÿþýý
z&SSHTunnelForwarder._process_deprecatedc              
   C   sÌ   d}t jt jt jf}tt dƒr*|t jf7 }|r4|fn|D ]Ž}z.|j| |d�}|rb| d | |¡¡ W  qÈW q8 t j	k
rš   |r�| 
d | ¡¡ Y  qÈY q8 t jk
rÄ   |rÀ| d | |¡¡ Y q8X q8|S )a�  
        Get SSH Public key from a private key file, given an optional password

        Arguments:
            pkey_file (str):
                File containing a private key (RSA, DSS or ECDSA)
        Keyword Arguments:
            pkey_password (Optional[str]):
                Password to decrypt the private key
            logger (Optional[logging.Logger])
        Return:
            paramiko.Pkey
        Nrý   )Úpasswordz/Private key file ({0}, {1}) successfully loadedz Password is required for key {0}zFPrivate key file ({0}) could not be loaded as type {1} or bad password)r‚   r  r  r  r  rý   Zfrom_private_key_filer¾   r   ZPasswordRequiredExceptionr†   rƒ   )rþ   r  rÿ   r8   r   Z	key_typesZ
pkey_classr   r   r   r  ÿ  s:    
þ ÿ
ÿ
 þz(SSHTunnelForwarder.read_private_key_filec                 C   sž   | j r| j d¡ dS |  ¡  | js2| jtdd� | jD ]>}tj	| j
|fd t|jƒ¡d�}| j|_| ¡  |  |¡ q8t| j ¡ ƒ| _ | j sš|  td¡ dS )z Start the SSH tunnels zAlready started!Nz*Could not establish session to SSH gateway)r  zSrv-{0})r²   rb   r    z(An error occurred while opening tunnels.)r×   r8   r®   r*  r"  rË   r]   rµ   Ú	threadingÚThreadÚ_serve_forever_wrapperr   rO   rž   rÉ   r  Ústartr¶   r0   r°   Úvaluesrj   )ra   r·   Úthreadr   r   r   r6  ,  s,    ÿ
ýÿzSSHTunnelForwarder.startc                 C   sR   | j  d¡ d dd„ | jD ƒ¡p$d}| j  d| ¡ | j|d� g | _i | _dS )	aÀ  
        Shut the tunnel down. By default we are always waiting until closing
        all connections. You can use `force=True` to force close connections

        Keyword Arguments:
            force (bool):
                Force close current connections

                Default: False

                .. versionadded:: 0.2.2

        .. note:: This **had** to be handled with care before ``0.1.0``:

            - if a port redirection is opened
            - the destination is not reachable
            - we attempt a connection to that tunnel (``SYN`` is sent and
              acknowledged, then a ``FIN`` packet is sent and never
              acknowledged... weird)
            - we try to shutdown: it will not succeed until ``FIN_WAIT_2`` and
              ``CLOSE_WAIT`` time out.

        .. note::
            Handle these scenarios with :attr:`.tunnel_is_up`: if False, server
            ``shutdown()`` will be skipped on that tunnel
        zClosing all open connections...z, c                 s   s   | ]}t |jƒV  qd S r*   )rO   r}   )r,   Úkr   r   r   r.   `  s     z*SSHTunnelForwarder.stop.<locals>.<genexpr>ÚNonezListening tunnels: ©ÚforceN)r8   rq   r  rµ   r¾   Ú_stop_transportr°   )ra   r<  Zopened_address_textr   r   r   ÚstopC  s    ÿþzSSHTunnelForwarder.stopc                 C   s   |   ¡  dS )z3 Stop the an active tunnel, alias to :meth:`.stop` N©r>  re   r   r   r   r„   g  s    zSSHTunnelForwarder.closec                 C   s   |   ¡  |  ¡  dS )z/ Restart connection to the gateway and tunnels N)r>  r6  re   r   r   r   Úrestartk  s    zSSHTunnelForwarder.restartc              	   C   s  | j D ]~}| j d t| ¡ ƒ¡¡ z4|  ¡ | _| jj| j	| j
|d� | jjrVW  dS W q tjk
r‚   | j d¡ |  ¡  Y qX q| j�r| j d dt| jƒ ¡¡ z4|  ¡ | _| jj| j	| j
| jd� | jjrÜW dS W n, tjk
�r
   | j d¡ |  ¡  Y nX | j d¡ dS )	z÷
        Open connection to SSH gateway
         - First try with all keys loaded from an SSH agent (if allowed)
         - Then with those passed directly or read from ~/.ssh/config
         - As last resort, try with a provided password
        zTrying to log in with key: {0})ÚhostkeyÚusernamer  NzAuthentication errorz#Trying to log in with password: {0}Ú*)rA  rB  r2  z$Could not open connection to gateway)rã   r8   r¾   r   r   Úget_fingerprintr!  rÁ   r½   rÕ   rß   r×   r‚   ZAuthenticationExceptionr=  rÑ   rú   r†   )ra   Úkeyr   r   r   r#  p  s>    


ÿ

þ
ÿ

þ
z&SSHTunnelForwarder._connect_to_gatewayr   c                 C   sN   | j  d t|jƒt|jƒ¡¡ | |¡ | j  d t|jƒt|jƒ¡¡ dS )zB
        Wrapper for the server created for a SSH forward
        zOpening tunnel: {0} <> {1}zTunnel: {0} <> {1} releasedN)r8   rq   r   rO   r}   rr   Úserve_forever)ra   r·   Úpoll_intervalr   r   r   r5  •  s    
þ

þz)SSHTunnelForwarder._serve_forever_wrapperc                 C   sT  z|   ¡  W n2 ttfk
r> } z| j |¡ W 5 d}~X Y nX |rj| jrj| j d¡ | j ¡  | j 	¡  | j
D ]¤}| j|j r„dnd}| j d t|jƒt|jƒ|¡¡ | ¡  | ¡  t|tƒrpzt |j¡ W qp tk
�r } z| j d |jt|ƒ¡¡ W 5 d}~X Y qpX qpd| _| j�rD| j d¡ | j ¡  | j 	¡  | j d¡ dS )	z< Close the underlying transport when nothing more is needed NzClosing ssh transportÚupZdownz&Shutting down tunnel: {0} <> {1} ({2})z Unable to unlink socket {0}: {1}FzTransport is closed)Ú_check_is_startedr]   rj   r8   r®   r"  rq   rÁ   r„   Zstop_threadrµ   r°   r}   r   rO   rr   ÚshutdownÚserver_closer   rª   r   Úunlinkr�   r†   r‡   r×   r¾   )ra   r<  rˆ   r·   Ústatusr   r   r   r=  ¤  sB    ÿ




ý

 ÿ

z"SSHTunnelForwarder._stop_transportc                 C   s(   |   ¡  t| jƒdkrtdƒ‚| jd S )Nr   z7Use .local_bind_ports property for more than one tunnelr   )rI  rú   rµ   r]   Úlocal_bind_portsre   r   r   r   Úlocal_bind_portÇ  s    ÿz"SSHTunnelForwarder.local_bind_portc                 C   s(   |   ¡  t| jƒdkrtdƒ‚| jd S )Nr   z7Use .local_bind_hosts property for more than one tunnelr   )rI  rú   rµ   r]   Úlocal_bind_hostsre   r   r   r   Úlocal_bind_hostÑ  s    ÿz"SSHTunnelForwarder.local_bind_hostc                 C   s(   |   ¡  t| jƒdkrtdƒ‚| jd S )Nr   z;Use .local_bind_addresses property for more than one tunnelr   )rI  rú   rµ   r]   ræ   re   r   r   r   rÍ   Û  s    ÿz%SSHTunnelForwarder.local_bind_addressc                 C   s   |   ¡  dd„ | jD ƒS )zU
        Return a list containing the ports of local side of the TCP tunnels
        c                 S   s   g | ]}|j d k	r|j ‘qS r*   )rž   ©r,   Z_serverr   r   r   rX   ë  s    
ÿz7SSHTunnelForwarder.local_bind_ports.<locals>.<listcomp>©rI  rµ   re   r   r   r   rN  å  s    z#SSHTunnelForwarder.local_bind_portsc                 C   s   |   ¡  dd„ | jD ƒS )zU
        Return a list containing the IP addresses listening for the tunnels
        c                 S   s   g | ]}|j d k	r|j ‘qS r*   )r�   rR  r   r   r   rX   ô  s    
ÿz7SSHTunnelForwarder.local_bind_hosts.<locals>.<listcomp>rS  re   r   r   r   rP  î  s    z#SSHTunnelForwarder.local_bind_hostsc                 C   s   |   ¡  dd„ | jD ƒS )zU
        Return a list of (IP, port) pairs for the local side of the tunnels
        c                 S   s   g | ]
}|j ‘qS r   )r}   rR  r   r   r   rX   ý  s     z;SSHTunnelForwarder.local_bind_addresses.<locals>.<listcomp>rS  re   r   r   r   ræ   ÷  s    z'SSHTunnelForwarder.local_bind_addressesc                    s   t ‡ fdd„ˆ jD ƒƒS )zY
        Return a dictionary containing the active local<>remote tunnel_bindings
        c                 3   s&   | ]}ˆ j |j r|j|jfV  qd S r*   )r°   r}   rr   rR  re   r   r   r.     s   þz5SSHTunnelForwarder.tunnel_bindings.<locals>.<genexpr>)Údictrµ   re   r   re   r   Útunnel_bindingsÿ  s    ÿz"SSHTunnelForwarder.tunnel_bindingsc                 C   s   d| j kr| j ¡ rdS dS )z3 Return True if the underlying SSH transport is up rÁ   TF)Ú__dict__rÁ   r"  re   r   r   r   r"    s    ÿþzSSHTunnelForwarder.is_activec                 C   s(   | j sd}t|ƒ‚| js$d}t|ƒ‚d S )Nz-Server is not started. Please .start() first!z/Tunnels are not started. Please .start() first!)r"  r]   r×   rj   )ra   r&  r   r   r   rI    s    z$SSHTunnelForwarder._check_is_startedc                 C   sê   | j t| jƒrdd„ | jD ƒnd dœ}t|ƒ tj dddddd	d
dddddddg¡}| | j| j	| j
| jrx| jjd nd| j|| jrŒ| jnd| jr˜dnd| js¤dn
d | j¡| jr¸dnd| jrÄdnd| jrÐdndt | jj¡| j| j¡S )Nc                 S   s    g | ]}|  ¡ t| ¡ ƒf‘qS r   )Úget_namer   rD  )r,   rE  r   r   r   rX     s   ÿz.SSHTunnelForwarder.__str__.<locals>.<listcomp>)r2  Zpkeysz
{0} objectzssh gateway: {1}:{2}z
proxy: {3}zusername: {4}zauthentication: {5}zhostkey: {6}zstatus: {7}startedzkeepalive messages: {8}ztunnel connection check: {9}z#concurrent connections: {10}allowedzcompression: {11}requestedzlogging level: {12}zlocal binds: {13}zremote binds: {14}r   Únoznot checkedr_   znot Údisabledzevery {0} secZenabled)rÑ   r0   rã   r\   r   Úlinesepr  r   Ú	__class__r   rÐ   rà   r  rß   rÕ   r×   rÖ   r´   rÅ   rá   r3   ÚgetLevelNamer8   rH   rÜ   rÛ   )ra   Úcredentialsr'  r   r   r   rf     sR    þÿüó

ðzSSHTunnelForwarder.__str__c                 C   s   |   ¡ S r*   )rf   re   r   r   r   Ú__repr__C  s    zSSHTunnelForwarder.__repr__c                 C   s0   z|   ¡  | W S  tk
r*   |  ¡  Y nX d S r*   )r6  ÚKeyboardInterruptÚ__exit__re   r   r   r   Ú	__enter__F  s
    zSSHTunnelForwarder.__enter__c                 G   s   | j dd� d S )NTr;  r?  )ra   rb   r   r   r   r`  M  s    zSSHTunnelForwarder.__exit__c                 C   s(   | j s| jr$| j d¡ | jdd� d S )Nz�It looks like you didn't call the .stop() before the SSHTunnelForwarder obj was collected by the garbage collector! Running .stop(force=True)Tr;  )r"  r×   r8   r®   r>  re   r   r   r   Ú__del__P  s
    ÿzSSHTunnelForwarder.__del__)NNNNNN)N)NNF)NNNTNN)F)NNN)F)r   )F)4r   rg   rh   ri   r´   r¨   rÉ   r  r³   r¯   r¶   rÄ   rÇ   rÈ   rÎ   ÚSSH_CONFIG_FILErd   ÚstaticmethodrÞ   rû   rù   rÝ   râ   r]   rË   r!  r*  rÚ   rØ   r  r6  r>  r„   r@  r#  r5  r=  r¤   rO  rQ  rÍ   rN  rP  ræ   rU  r"  rI  rf   r^  ra  r`  rb  r   r   r   r   r­   ä  sÂ     $
(ë
k      ù<8
      û&
   ý,
$%

#
	
	
	




	)r­   c                  O   s¬   t | dd¡| dd¡d�|d< | dd¡}dD ]}t |||¡}q0| dd¡}| d	d
¡}| dd¡}|rxt dt¡ | s˜t|t	ƒrŽ|f} n
||ff} t| |Ž}||_
|S )a  
    Open an SSH Tunnel, wrapper for :class:`SSHTunnelForwarder`

    Arguments:
        destination (Optional[tuple]):
            SSH server's IP address and port in the format
            (``ssh_address``, ``ssh_port``)

    Keyword Arguments:
        debug_level (Optional[int or str]):
            log level for :class:`logging.Logger` instance, i.e. ``DEBUG``

        skip_tunnel_checkup (boolean):
            Enable/disable the local side check and populate
            :attr:`~SSHTunnelForwarder.tunnel_is_up`

            Default: True

            .. versionadded:: 0.1.0

    .. note::
        A value of ``debug_level`` set to 1 == ``TRACE`` enables tracing mode
    .. note::
        See :class:`SSHTunnelForwarder` for keyword arguments

    **Example**::

        from sshtunnel import open_tunnel

        with open_tunnel(SERVER,
                         ssh_username=SSH_USER,
                         ssh_port=22,
                         ssh_password=SSH_PASSWORD,
                         remote_bind_address=(REMOTE_HOST, REMOTE_PORT),
                         local_bind_address=('', LOCAL_PORT)) as server:
            def do_something(port):
                pass

            print("LOCAL PORTS:", server.local_bind_port)

            do_something(server.local_bind_port)
    r8   NÚdebug_level)r8   r6   r   rÏ   rÐ   ré   r´   TÚblock_on_closez­'block_on_close' is DEPRECATED. You should use either .stop() or .stop(force=True), depends on what you do with the active connections. This option has no affect since 0.3.0)rG   r±   r[   r­   rØ   r/  r0  r1  r   r   r´   )rb   rc   r   rè   rÐ   r´   rf  Z	forwarderr   r   r   Úopen_tunnelY  s0    ,
ÿ
ýü


rg  c                 C   s�   zP|   d¡}t|ƒdkr&|d }d}n|\}}|s<|s<t‚n|sDd}|t|ƒfW S  tk
rn   t d¡‚Y n tk
rŠ   t d¡‚Y nX dS )z“ Define type of data expected for remote and local bind address lists
        Returns a tuple (ip_address, port) whose elements are (str, int)
    ú:r   r   NZ22z-Address tuple must be of type IP_ADDRESS:PORTzBoth IP:PORT can't be missing!)Úsplitrú   r   r   r!   ÚargparseÚArgumentTypeError)Z	input_strZip_portÚ_ipZ_portr   r   r   Ú	_bindlist¤  s"    
ÿrm  c                 C   s¢  t jd t¡t jd�}|jdtdd� |jddtdd	d
� |jddtdddd� |jddtddd
� |jddtdg ddddd�	 |jddtdd dd!d"� |jd#d$td%d� |jd&d'd(d)td*d+� |jd,d-d.d/td0d+� |jd1d2d3d4d5� |jd6d7d8d9d: t	 
t¡¡d;� |jd<d=d>d?jtd@�dAdB� |jdCdDtdEddFdG� |jdHdIttdJdK t¡dL� |jdMdNd3dOdPdQ� |jdRdSdTdUdVdQ� |jdWdXddYdZd[d\� t| | ¡ƒS )]z2
    Parse arguments directly passed from CLI
    z(Pure python ssh tunnel utils
Version {0})ÚdescriptionÚformatter_classr
   zbSSH server IP address (GW for SSH tunnels)
set with "-- ssh_address" if immediately after -R or -L)r   Úhelpz-Uz
--usernamerß   zSSH server account username)r   Údestrp  z-pz--server_portrÐ   ré   z!SSH server TCP port (default: 22))r   rq  Údefaultrp  z-Pz
--passwordrÑ   zSSH server account passwordz-Rz--remote_bind_addressú+zIP:PORTTrç   z¼Remote bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n
Equivalent to ssh -Lxxxx:IP_ADDRESS:PORT
If port is omitted, defaults to 22.
Example: -R 10.10.10.10: 10.10.10.10:5900)r   Únargsrr  ÚmetavarÚrequiredrq  rp  z-Lz--local_bind_addressrC  ræ   aT  Local bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n
Elements may also be valid UNIX socket domains: 
/tmp/foo.sock /tmp/bar.sock ... /tmp/baz.sock
Equivalent to ssh -LPORT:xxxxxxxxx:xxxx, being the local IP address optional.
By default it will listen in all interfaces (0.0.0.0) and choose a random port.
Example: -L :40000)r   rt  rq  ru  rp  z-kz--ssh_host_keyzGateway's host keyz-Kz--private_key_filer   ZKEY_FILEzRSA/DSS/ECDSA private key file)rq  ru  r   rp  z-Sz--private_key_passwordrå   ZKEY_PASSWORDz"RSA/DSS/ECDSA private key passwordz-tz
--threadedÚ
store_truez+Allow concurrent connections to each tunnel)Úactionrp  z-vz	--verboser  r   z(Increase output verbosity (default: {0}))rx  rr  rp  z-Vz	--versionÚversionz%(prog)s {version})ry  zShow version number and quit)rx  ry  rp  z-xz--proxyrà   z'IP and port of SSH proxy to destination)r   rq  ru  rp  z-cz--configrä   z'SSH configuration file, defaults to {0})r   rr  rq  rp  z-zz
--compressrá   z1Request server for compression over SSH transport)rx  rq  rp  z-nz	--noagentÚstore_falserÓ   z*Disable looking for keys from an SSH agentz-dz--host_pkey_directoriesrÔ   ZFOLDERzGList of directories where SSH pkeys (in the format `id_*`) may be found)rt  rq  ru  rp  )rj  ÚArgumentParserr   Ú__version__ÚRawTextHelpFormatterÚadd_argumentrN   r   rm  r3   r\  r>   rc  ÚvarsÚ
parse_args)rb   Úparserr   r   r   Ú_parse_arguments¼  s   ÿýý ü û ü ø ú ý û û ý ÿü	 
ü û û ü ü ûr‚  c              	   K   sŒ   t | ƒ}t|ƒ t| d¡dƒ}tjtjtjtjt	g}| 
d|| ¡ | ¡ D ]\}}| 
||¡ qNtf |Ž�}|jr~tdƒ W 5 Q R X dS )a“   Pass input arguments to open_tunnel

        Mandatory: ssh_address, -R (remote bind address list)

        Optional:
        -U (username) we may gather it from SSH_CONFIG_FILE or current username
        -p (server_port), defaults to 22
        -P (password)
        -L (local_bind_address), default to 0.0.0.0:22
        -k (ssh_host_key)
        -K (private_key_file), may be gathered from SSH_CONFIG_FILE
        -S (private_key_password)
        -t (threaded), allow concurrent connections over tunnels
        -v (verbose), up to 3 (-vvv) to raise loglevel from ERROR to DEBUG
        -V (version)
        -x (proxy), ProxyCommand's IP:PORT, may be gathered from config file
        -c (ssh_config), ssh configuration file (defaults to SSH_CONFIG_FILE)
        -z (compress)
        -n (noagent), disable looking for keys from an Agent
        -d (host_pkey_directories), look for keys on these folders
    Úverboseé   re  z>

            Press <Ctrl-C> or <Enter> to stop!

            N)r‚  r\   Úminr[   r3   ÚERRORÚWARNINGÚINFOrI   rp   Ú
setdefaultÚitemsrg  r×   Úinput_)rb   ÚextrasÚ	argumentsÚ	verbosityZlevelsÚextrar^   Ztunnelr   r   r   Ú	_cli_mainY  s    ür�  Ú__main__)F)NNTT)NN)N)N)N)Hri   r   rB   r…   rî   r3   rj  r/  r3  r   Úbinasciir   r‚   rC   r�   rŒ   ÚSocketServerr�   Ú
basestringr   Ú	raw_inputr‹  rN   Úinputr|  Ú
__author__r  r€   r¨   rR   ÚLockrQ   r.  r†  r>   rp   ÚaddLevelNamer   r    ÚUnixStreamServerr�   r«   r"   r  rc  r   r   r)   r2   rG   r@   rA   rO   rT   r\   r�   r]   rj   ÚBaseRequestHandlerrk   rŠ   ÚThreadingMixInr¥   rª   r¬   Úobjectr­   rg  rm  r‚  r�  r   r   r   r   r   Ú<module>   s    üÿ	"
#    ý
;


Q3	#ÿ
        }K
 
,
