U
    2ÜŸj   ã                   @   sØ   d Z ddlZddlmZmZ ddlmZmZ ddlm	Z	m
Z
 G dd„ dejƒZG dd	„ d	ejƒZG d
d„ deƒZG dd„ deƒZG dd„ dejƒZdd„ ZG dd„ dejƒZdd„ ZeZdd„ ZeZdd„ Zdd„ ZdS )z¯
This module contains the implementation of the TCP forwarding, which allows
clients and servers to forward arbitrary TCP data across the connection.

Maintainer: Paul Swartz
é    N)ÚchannelÚcommon)ÚprotocolÚreactor)ÚHostnameEndpointÚconnectProtocolc                   @   s   e Zd Zdd„ Zdd„ ZdS )ÚSSHListenForwardingFactoryc                 C   s   || _ || _|| _d S ©N)ÚconnÚhostportÚklass)ÚselfÚ
connectionr   r   © r   ú@/tmp/pip-unpacked-wheel-4b529toj/twisted/conch/ssh/forwarding.pyÚ__init__   s    z#SSHListenForwardingFactory.__init__c                 C   sF   | j | jd�}t|ƒ}||_|j|jf}t| j|ƒ}| j ||¡ |S )N)r
   )	r   r
   ÚSSHForwardingClientÚclientÚhostÚportÚpackOpen_direct_tcpipr   ZopenChannel)r   Úaddrr   r   Z	addrTupleZchannelOpenDatar   r   r   ÚbuildProtocol   s    z(SSHListenForwardingFactory.buildProtocolN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r   r      s   r   c                   @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚSSHListenForwardingChannelc                 C   sH   | j jd| jd� t| jjƒdkr<| jjdd … }|  |¡ d| j_d S )Nzopened forwarding channel {id}©Úidé   ó    )Ú_logÚinfor   Úlenr   ÚbufÚwrite)r   ÚspecificDataÚbr   r   r   ÚchannelOpen$   s
    
z&SSHListenForwardingChannel.channelOpenc                 C   s   |   ¡  d S r	   )Úclosed©r   Úreasonr   r   r   Ú
openFailed+   s    z%SSHListenForwardingChannel.openFailedc                 C   s   | j j |¡ d S r	   )r   Ú	transportr%   ©r   Údatar   r   r   ÚdataReceived.   s    z'SSHListenForwardingChannel.dataReceivedc                 C   s   | j j ¡  d S r	   )r   r-   ÚloseConnection©r   r   r   r   ÚeofReceived1   s    z&SSHListenForwardingChannel.eofReceivedc                 C   s0   t | dƒr,| jjd| jd� | jj ¡  | `d S )Nr   z%closing local forwarding channel {id}r   )Úhasattrr!   r"   r   r   r-   r1   r2   r   r   r   r)   4   s    
z!SSHListenForwardingChannel.closedN)r   r   r   r(   r,   r0   r3   r)   r   r   r   r   r   #   s
   r   c                   @   s   e Zd ZdZdS )Ú SSHListenClientForwardingChannels   direct-tcpipN©r   r   r   Únamer   r   r   r   r5   ;   s   r5   c                   @   s   e Zd ZdZdS )Ú SSHListenServerForwardingChannels   forwarded-tcpipNr6   r   r   r   r   r8   ?   s   r8   c                   @   sD   e Zd ZdZeZdd„ Zdd„ Zdd„ Zdd	„ Z	d
d„ Z
dd„ ZdS )ÚSSHConnectForwardingChannelaó  
    Channel used for handling server side forwarding request.
    It acts as a client for the remote forwarding destination.

    @ivar hostport: C{(host, port)} requested by client as forwarding
        destination.
    @type hostport: L{tuple} or a C{sequence}

    @ivar client: Protocol connected to the forwarding destination.
    @type client: L{protocol.Protocol}

    @ivar clientBuf: Data received while forwarding channel is not yet
        connected.
    @type clientBuf: L{bytes}

    @var  _reactor: Reactor used for TCP connections.
    @type _reactor: A reactor.

    @ivar _channelOpenDeferred: Deferred used in testing to check the
        result of C{channelOpen}.
    @type _channelOpenDeferred: L{twisted.internet.defer.Deferred}
    c                 O   s*   t jj| f|ž|Ž || _d | _d| _d S )Nr    )r   Ú
SSHChannelr   r   r   Ú	clientBuf)r   r   ÚargsÚkwr   r   r   r   ]   s    z$SSHConnectForwardingChannel.__init__c                 C   s`   | j jd| jd | jd d� t| j| jd | jd ƒ}t|t| ƒƒ}| | j| j	¡ || _
dS )ú,
        See: L{channel.SSHChannel}
        zconnecting to {host}:{port}r   r   ©r   r   N)r!   r"   r   r   Ú_reactorr   r   ZaddCallbacksÚ
_setClientÚ_closeZ_channelOpenDeferred)r   r&   ÚepÚdr   r   r   r(   c   s      ÿz'SSHConnectForwardingChannel.channelOpenc                 C   sr   || _ | jjd| jd | jd d� | jr@| j j | j¡ d| _| j jdd… rf|  | j jdd… ¡ d| j _dS )zà
        Called when the connection was established to the forwarding
        destination.

        @param client: Client protocol connected to the forwarding destination.
        @type  client: L{protocol.Protocol}
        zconnected to {host}:{port}r   r   r?   Nr    )r   r!   r"   r   r;   r-   r%   r$   )r   r   r   r   r   rA   o   s      ÿz&SSHConnectForwardingChannel._setClientc                 C   s,   | j jd| jd | jd |d� |  ¡  dS )z½
        Called when failed to connect to the forwarding destination.

        @param reason: Reason why connection failed.
        @type  reason: L{twisted.python.failure.Failure}
        z,failed to connect to {host}:{port}: {reason}r   r   )r   r   r+   N)r!   Úerrorr   r1   r*   r   r   r   rB   ‚   s    üz"SSHConnectForwardingChannel._closec                 C   s(   | j r| j j |¡ n|  j|7  _dS )r>   N)r   r-   r%   r;   r.   r   r   r   r0   ‘   s    z(SSHConnectForwardingChannel.dataReceivedc                 C   s<   | j r8| jjd| jd� | j jr(|  ¡  | j j ¡  | ` dS )r>   z%closed remote forwarding channel {id}r   N)r   r!   r"   r   r   r1   r-   r2   r   r   r   r)   š   s    z"SSHConnectForwardingChannel.closedN)r   r   r   Ú__doc__r   r@   r   r(   rA   rB   r0   r)   r   r   r   r   r9   C   s   	r9   c                 C   s   t |ƒ\}}t|| ||d�S )N)ÚremoteWindowÚremoteMaxPacketÚavatar)ÚunpackOpen_direct_tcpipr9   )rG   rH   r/   rI   ZremoteHPZorigHPr   r   r   ÚopenConnectForwardingClient¦   s    ürK   c                   @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )r   c                 C   s   || _ d| _d S )Nó    )r   r$   )r   r   r   r   r   r   ±   s    zSSHForwardingClient.__init__c                 C   s&   | j r|  j |7  _ n| j |¡ d S r	   )r$   r   r%   r.   r   r   r   r0   µ   s    z SSHForwardingClient.dataReceivedc                 C   s   | j r| j  ¡  d | _ d S r	   )r   r1   r*   r   r   r   ÚconnectionLost»   s    
z"SSHForwardingClient.connectionLostN)r   r   r   r   r0   rM   r   r   r   r   r   °   s   r   c                 C   sl   | \}}|\}}t |tƒr$| d¡}t |tƒr8| d¡}t |¡t d|¡ }t |¡t d|¡ }|| S )a  
    Pack the data suitable for sending in a CHANNEL_OPEN packet.

    @type destination: L{tuple}
    @param destination: A tuple of the (host, port) of the destination host.

    @type source: L{tuple}
    @param source: A tuple of the (host, port) of the source host.
    úutf-8ú>L)Ú
isinstanceÚstrÚencoder   ÚNSÚstructÚpack)ZdestinationÚsourceÚconnHostÚconnPortÚorigHostÚorigPortr
   Úorigr   r   r   r   Á   s    




r   c                 C   s”   t  | ¡\}}t|tƒr"| d¡}tt d|dd… ¡d ƒ}t  |dd… ¡\}}t|tƒrh| d¡}tt d|dd… ¡d ƒ}||f||ffS )z#Unpack the data to a usable format.rN   rO   Né   r   ©r   ZgetNSrP   ÚbytesÚdecodeÚintrT   Úunpack)r/   rW   ÚrestrX   rY   rZ   r   r   r   rJ   Ù   s    



rJ   c                 C   s   | \}}t  |¡t d|¡ S )zv
    Pack the data for tcpip forwarding.

    @param peer: A tuple of the (host, port) .
    @type peer: L{tuple}
    rO   )r   rS   rT   rU   )Zpeerr   r   r   r   r   ÚpackGlobal_tcpip_forwardé   s    rc   c                 C   sF   t  | ¡\}}t|tƒr"| d¡}tt d|d d… ¡d ƒ}||fS )NrN   rO   r\   r   r]   )r/   r   rb   r   r   r   r   ÚunpackGlobal_tcpip_forwardô   s
    

rd   )rF   rT   Ztwisted.conch.sshr   r   Ztwisted.internetr   r   Ztwisted.internet.endpointsr   r   ZFactoryr   r:   r   r5   r8   r9   rK   ÚProtocolr   r   ZpackOpen_forwarded_tcpiprJ   ZunpackOpen_forwarded_tcpiprc   rd   r   r   r   r   Ú<module>   s$   c
