U
     T‚g—I  ã                   @   s8  d Z ddlZzddlmZ W n ek
r0   Y nX ddlmZmZ ddl	m
Z
mZ ddlmZmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ G dd„ dƒZeejƒG dd„ dƒƒZeejejƒG dd„ dƒƒZdd„ Zdd„ ZG dd„ dƒZ d#dd„Z!eedddfdd„Z"dd„ Z#G dd „ d ƒZ$d$d!d"„Z%dS )%z0
Utilities and helpers for simulating a network
é    N)ÚError)ÚdirectlyProvidesÚimplementer)ÚerrorÚ
interfaces)ÚTCP4ClientEndpointÚTCP4ServerEndpoint)ÚConnectionRefusedError)ÚFactoryÚProtocol)ÚMemoryReactorClock)ÚFailurec                   @   s*   e Zd Zdd„ Zedœdd„Zdd„ ZdS )	ÚTLSNegotiationc                 C   s   || _ || _d| _|| _d S )NF)ÚobjÚconnectStateÚsentÚreadyToSend)Úselfr   r   © r   ú6/tmp/pip-unpacked-wheel-1_7di8ic/twisted/test/iosim.pyÚ__init__   s    zTLSNegotiation.__init__©Úreturnc                 C   s   d| j ›d�S )NzTLSNegotiation(ú))r   ©r   r   r   r   Ú__repr__!   s    zTLSNegotiation.__repr__c                 C   s"   | j  |j ¡stƒ |_| ¡  d S ©N)r   ZiosimVerifyÚNativeOpenSSLErrorÚdisconnectReasonÚloseConnection)r   ÚotherZtptr   r   r   ÚpretendToVerify$   s    zTLSNegotiation.pretendToVerifyN)Ú__name__Ú
__module__Ú__qualname__r   Ústrr   r!   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZdS )ÚFakeAddressz]
    The default address type for the host and peer of L{FakeTransport}
    connections.
    N)r"   r#   r$   Ú__doc__r   r   r   r   r&   -   s   r&   c                   @   s  e Zd ZdZee ¡ fdd„ƒZdZdZ	dZ
e d¡ZdZdZdZd;dd„Zed	œd
d„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Z d&d'„ Z!d(d)„ Z"d<d+d,„Z#d-d.„ Z$d/d0„ Z%d1d2„ Z&d3d4„ Z'd5d6„ Z(d7d8„ Z)d9d:„ Z*dS )=ÚFakeTransportzØ
    A wrapper around a file-like object to make it behave as a Transport.

    This doesn't actually stream the file to the attached protocol,
    and is thus useful mainly as a utility for debugging protocols.
    c                 C   s   t t| ƒƒS r   )ÚintÚnext)Úcounterr   r   r   Ú<lambda>>   ó    zFakeTransport.<lambda>r   zConnection doneNc                 C   sH   || _ || _g | _|  ¡ | _|dkr*tƒ }|| _|dkr>tƒ }|| _dS )aÔ  
        @param protocol: This transport will deliver bytes to this protocol.
        @type protocol: L{IProtocol} provider

        @param isServer: C{True} if this is the accepting side of the
            connection, C{False} if it is the connecting side.
        @type isServer: L{bool}

        @param hostAddress: The value to return from C{getHost}.  L{None}
            results in a new L{FakeAddress} being created to use as the value.
        @type hostAddress: L{IAddress} provider or L{None}

        @param peerAddress: The value to return from C{getPeer}.  L{None}
            results in a new L{FakeAddress} being created to use as the value.
        @type peerAddress: L{IAddress} provider or L{None}
        N)ÚprotocolÚisServerÚstreamÚ_nextserialÚserialr&   ÚhostAddressÚpeerAddress)r   r.   r/   r3   r4   r   r   r   r   G   s    
zFakeTransport.__init__r   c                 C   s    d  | jrdpd| j| jjj¡S )NzFakeTransport<{},{},{}>ÚSÚC)Úformatr/   r2   r.   Ú	__class__r"   r   r   r   r   r   c   s
    ýzFakeTransport.__repr__c                 C   s2   | j r
d S | jd k	r"| j |¡ n| j |¡ d S r   )ÚdisconnectingÚtlsÚtlsbufÚappendr0   )r   Údatar   r   r   Úwritej   s
    
zFakeTransport.writec                 C   s   | j r| js| j  ¡  d S r   ©ÚproducerÚstreamingProducerÚresumeProducingr   r   r   r   Ú_checkProducert   s    zFakeTransport._checkProducerc                 C   s   || _ || _|s| ¡  dS )z.
        From abstract.FileDescriptor
        Nr?   )r   r@   Z	streamingr   r   r   ÚregisterProducerz   s    zFakeTransport.registerProducerc                 C   s
   d | _ d S r   )r@   r   r   r   r   ÚunregisterProducerƒ   s    z FakeTransport.unregisterProducerc                 C   s   |   ¡  |  ¡  d S r   )rE   r   r   r   r   r   ÚstopConsuming†   s    zFakeTransport.stopConsumingc                 C   s   |   d |¡¡ d S )Nr-   )r>   Újoin)r   Ziovecr   r   r   ÚwriteSequenceŠ   s    zFakeTransport.writeSequencec                 C   s
   d| _ d S ©NT©r9   r   r   r   r   r   �   s    zFakeTransport.loseConnectionc                 C   s
   d| _ dS )zp
        For the time being, this is the same as loseConnection; no buffered
        data will be lost.
        TNrJ   r   r   r   r   ÚabortConnection�   s    zFakeTransport.abortConnectionc                 C   s,   | j d k	rtƒ }n| j}| j t|ƒ¡ d S r   )r:   r   r   r.   ZconnectionLostr   )r   Úerrr   r   r   ÚreportDisconnect—   s    
zFakeTransport.reportDisconnectc                 C   s   dS )zM
        Identify this transport/event source to the logging system.
        Ziosimr   r   r   r   r   Ú	logPrefix    s    zFakeTransport.logPrefixc                 C   s   | j S r   )r4   r   r   r   r   ÚgetPeer¦   s    zFakeTransport.getPeerc                 C   s   | j S r   )r3   r   r   r   r   ÚgetHost©   s    zFakeTransport.getHostc                 C   s   d S r   r   r   r   r   r   rB   ¬   s    zFakeTransport.resumeProducingc                 C   s   d S r   r   r   r   r   r   ÚpauseProducing°   s    zFakeTransport.pauseProducingc                 C   s   |   ¡  d S r   )r   r   r   r   r   ÚstopProducing´   s    zFakeTransport.stopProducingTc                 C   s    | j |A }t||ƒ| _g | _d S r   )r/   r   r:   r;   )r   ZcontextFactoryZbeNormalr   r   r   r   ÚstartTLS·   s    
zFakeTransport.startTLSc                 C   sH   | j }|rg | _ d |¡S | jdk	r@| jjr:d| j_| jS dS ndS dS )zÁ
        Get the pending writes from this transport, clearing them from the
        pending buffer.

        @return: the bytes written with C{transport.write}
        @rtype: L{bytes}
        r-   NT)r0   rG   r:   r   r   )r   r5   r   r   r   ÚgetOutBuffer¿   s    

zFakeTransport.getOutBufferc                 C   st   t |tƒrd| jd k	st‚| jjrZ| j || ¡ d | _| jd  }| _|  |¡ t| t	j
ƒ qpd| j_n| j |¡ d S rI   )Ú
isinstancer   r:   ÚAssertionErrorr   r!   r;   rH   r   r   ZISSLTransportr   r.   ZdataReceived)r   ÚbufÚbr   r   r   ÚbufferReceivedÕ   s    


zFakeTransport.bufferReceivedc                 C   s   d S r   r   r   r   r   r   ÚgetTcpKeepAliveè   s    zFakeTransport.getTcpKeepAlivec                 C   s   d S r   r   r   r   r   r   ÚgetTcpNoDelayì   s    zFakeTransport.getTcpNoDelayc                 C   s   d S r   r   r   r   r   r   ÚloseWriteConnectionð   s    z!FakeTransport.loseWriteConnectionc                 C   s   d S r   r   ©r   Zenabledr   r   r   ÚsetTcpKeepAliveô   s    zFakeTransport.setTcpKeepAlivec                 C   s   d S r   r   r]   r   r   r   ÚsetTcpNoDelayø   s    zFakeTransport.setTcpNoDelay)NN)T)+r"   r#   r$   r'   ÚstaticmethodÚ	itertoolsÚcountr1   Úclosedr9   Údisconnectedr   ZConnectionDoner   r@   rA   r:   r   r%   r   r>   rC   rD   rE   rF   rH   r   rK   rM   rN   rO   rP   rB   rQ   rR   rS   rT   rY   rZ   r[   r\   r^   r_   r   r   r   r   r(   5   sD   


		
r(   c                 C   s   t | dd�S )zø
    Create and return a new in-memory transport hooked up to the given protocol.

    @param clientProtocol: The client protocol to use.
    @type clientProtocol: L{IProtocol} provider

    @return: The transport.
    @rtype: L{FakeTransport}
    F©r/   ©r(   )ÚclientProtocolr   r   r   ÚmakeFakeClientý   s    
rh   c                 C   s   t | dd�S )zø
    Create and return a new in-memory transport hooked up to the given protocol.

    @param serverProtocol: The server protocol to use.
    @type serverProtocol: L{IProtocol} provider

    @return: The transport.
    @rtype: L{FakeTransport}
    Tre   rf   )ÚserverProtocolr   r   r   ÚmakeFakeServer
  s    
rj   c                   @   s.   e Zd ZdZddd„Zddd„Zdd	d
„ZdS )ÚIOPumpz�
    Utility to pump data between clients and servers for protocol testing.

    Perhaps this is a utility worthy of being in protocol.py?
    Nc                 C   s6   || _ || _|| _|| _|| _|d kr,tƒ }|| _d S r   )ÚclientÚserverÚclientIOÚserverIOÚdebugr   Úclock)r   rl   rm   rn   ro   rp   rq   r   r   r   r     s    zIOPump.__init__FTc                 C   s8   d}t dƒD ]}|  ||¡r"d}q q4qds4tdƒ‚|S )zk
        Pump until there is no more input or output.

        Returns whether any data was moved.
        Fiè  Tr   zToo long)ÚrangeÚpumprV   )r   rp   ÚadvanceClockÚresultÚ_r   r   r   Úflush(  s    zIOPump.flushc                 C   s<  |r| j  d¡ | js|r"tdƒ | j ¡ }| j ¡ }| j ¡  | j ¡  | jsT|r„tdƒ |rptdt|ƒ ƒ |r„tdt|ƒ ƒ |r”| j 	|¡ |r¤| j 	|¡ |s¬|r°dS | jj
rð| jjsð| jsÊ|rÒtdƒ d| j_d| j_
| j ¡  dS | jj
�r8| jj�s8| j�s|�rtdƒ d| j_d| j_
| j ¡  dS d	S )
z·
        Move data back and forth, while also triggering any currently pending
        scheduled calls (i.e. C{callLater(0, f)}).

        Returns whether any data was moved.
        r   z
-- GLUG --Ú.zC: zS: Tz* Cz* SF)rq   Zadvancerp   Úprintro   rT   rn   rC   ÚreprrY   r9   rd   rM   )r   rp   rt   ZsDataZcDatar   r   r   rs   8  sF    








zIOPump.pump)N)FT)FT)r"   r#   r$   r'   r   rw   rs   r   r   r   r   rk     s   


rk   FTc                 C   s8   |   |¡ |  |¡ t|| ||||d�}|r4| ¡  |S )aÓ  
    Create a new L{IOPump} connecting two protocols.

    @param serverProtocol: The protocol to use on the accepting side of the
        connection.
    @type serverProtocol: L{IProtocol} provider

    @param serverTransport: The transport to associate with C{serverProtocol}.
    @type serverTransport: L{FakeTransport}

    @param clientProtocol: The protocol to use on the initiating side of the
        connection.
    @type clientProtocol: L{IProtocol} provider

    @param clientTransport: The transport to associate with C{clientProtocol}.
    @type clientTransport: L{FakeTransport}

    @param debug: A flag indicating whether to log information about what the
        L{IOPump} is doing.
    @type debug: L{bool}

    @param greet: Should the L{IOPump} be L{flushed <IOPump.flush>} once before
        returning to put the protocols into their post-handshake or
        post-server-greeting state?
    @type greet: L{bool}

    @param clock: An optional L{Clock}. Pumping the resulting L{IOPump} will
        also increase clock time by a small increment.

    @return: An L{IOPump} which connects C{serverProtocol} and
        C{clientProtocol} and delivers bytes between them when it is pumped.
    @rtype: L{IOPump}
    ©rq   )ZmakeConnectionrk   rw   )ri   ÚserverTransportrg   ÚclientTransportrp   Úgreetrq   rs   r   r   r   Úconnecte  s    *

úr   c                 C   s8   |ƒ }| ƒ }||ƒ}	||ƒ}
||t ||
||	|||d�fS )a‰  
    Connect a given server and client class to each other.

    @param ServerClass: a callable that produces the server-side protocol.
    @type ServerClass: 0-argument callable returning L{IProtocol} provider.

    @param ClientClass: like C{ServerClass} but for the other side of the
        connection.
    @type ClientClass: 0-argument callable returning L{IProtocol} provider.

    @param clientTransportFactory: a callable that produces the transport which
        will be attached to the protocol returned from C{ClientClass}.
    @type clientTransportFactory: callable taking (L{IProtocol}) and returning
        L{FakeTransport}

    @param serverTransportFactory: a callable that produces the transport which
        will be attached to the protocol returned from C{ServerClass}.
    @type serverTransportFactory: callable taking (L{IProtocol}) and returning
        L{FakeTransport}

    @param debug: Should this dump an escaped version of all traffic on this
        connection to stdout for inspection?
    @type debug: L{bool}

    @param greet: Should the L{IOPump} be L{flushed <IOPump.flush>} once before
        returning to put the protocols into their post-handshake or
        post-server-greeting state?
    @type greet: L{bool}

    @param clock: An optional L{Clock}. Pumping the resulting L{IOPump} will
        also increase clock time by a small increment.

    @return: the client protocol, the server protocol, and an L{IOPump} which,
        when its C{pump} and C{flush} methods are called, will move data
        between the created client and server protocol instances.
    @rtype: 3-L{tuple} of L{IProtocol}, L{IProtocol}, L{IOPump}
    r{   )r   )ZServerClassZClientClassZclientTransportFactoryZserverTransportFactoryrp   r~   rq   ÚcÚsZcioÚsior   r   r   ÚconnectedServerAndClientŸ  s
    .rƒ   c                 C   s2   | \}}}}}|\}}}	}
||kr*||fS dS dS )a'  
    Should the client and server described by the arguments be connected to
    each other, i.e. do their port numbers match?

    @param clientInfo: the args for connectTCP
    @type clientInfo: L{tuple}

    @param serverInfo: the args for listenTCP
    @type serverInfo: L{tuple}

    @return: If they do match, return factories for the client and server that
        should connect; otherwise return L{None}, indicating they shouldn't be
        connected.
    @rtype: L{None} or 2-L{tuple} of (L{ClientFactory},
        L{IProtocolFactory})
    Nr   )Ú
clientInfoÚ
serverInfoZ
clientHostZ
clientPortÚclientFactoryZclientTimeoutZclientBindAddressZ
serverPortÚserverFactoryZserverBacklogZserverInterfacer   r   r   Ú_factoriesShouldConnectÔ  s    úrˆ   c                   @   s4   e Zd ZdZdd„ Zd
dd„Zeeƒ ƒfdd„Zd	S )ÚConnectionCompleterz¬
    A L{ConnectionCompleter} can cause synthetic TCP connections established by
    L{MemoryReactor.connectTCP} and L{MemoryReactor.listenTCP} to succeed or
    fail.
    c                 C   s
   || _ dS )z±
        Create a L{ConnectionCompleter} from a L{MemoryReactor}.

        @param memoryReactor: The reactor to attach to.
        @type memoryReactor: L{MemoryReactor}
        N)Ú_reactor)r   ÚmemoryReactorr   r   r   r   ú  s    zConnectionCompleter.__init__Fc                 C   s”   | j }t|jƒD ]~\}}|jD ]n}t||ƒ}|r|j |¡ |j |¡ |\}}| d¡}	| d¡}
t	|
ƒ}t
|	ƒ}t|
||	||ƒ    S qqdS )a“  
        Complete a single TCP connection established on this
        L{ConnectionCompleter}'s L{MemoryReactor}.

        @param debug: A flag; whether to dump output from the established
            connection to stdout.
        @type debug: L{bool}

        @return: a pump for the connection, or L{None} if no connection could
            be established.
        @rtype: L{IOPump} or L{None}
        N)rŠ   Ú	enumerateÚ
tcpClientsZ
tcpServersrˆ   ÚremoveÚ
connectorsÚpopZbuildProtocolrj   rh   r   )r   rp   r‹   Z	clientIdxr„   r…   Z	factoriesr†   r‡   rg   ri   r|   r}   r   r   r   ÚsucceedOnce  s&    



ûzConnectionCompleter.succeedOncec                 C   s(   | j j d¡d  | j j d¡|¡ dS )zà
        Fail a single TCP connection established on this
        L{ConnectionCompleter}'s L{MemoryReactor}.

        @param reason: the reason to provide that the connection failed.
        @type reason: L{Failure}
        r   é   N)rŠ   r�   r�   ZclientConnectionFailedr�   )r   Úreasonr   r   r   ÚfailOnce$  s     ÿzConnectionCompleter.failOnceN)F)	r"   r#   r$   r'   r   r‘   r   r	   r”   r   r   r   r   r‰   ó  s   	
!r‰   c                 C   s8   t ƒ }t|ddƒ}t|dƒ}| t t¡¡ |t|ƒfS )a…  
    Create an endpoint that can be fired on demand.

    @param debug: A flag; whether to dump output from the established
        connection to stdout.
    @type debug: L{bool}

    @return: A client endpoint, and an object that will cause one of the
        L{Deferred}s returned by that client endpoint.
    @rtype: 2-L{tuple} of (L{IStreamClientEndpoint}, L{ConnectionCompleter})
    z0.0.0.0iá  )r   r   r   Úlistenr
   ZforProtocolr   r‰   )rp   ZreactorZclientEndpointZserverEndpointr   r   r   ÚconnectableEndpoint1  s
    
r–   )FTN)F)&r'   ra   ZOpenSSL.SSLr   r   ÚImportErrorZzope.interfacer   r   Ztwisted.internetr   r   Ztwisted.internet.endpointsr   r   Ztwisted.internet.errorr	   Ztwisted.internet.protocolr
   r   Ztwisted.internet.testingr   Ztwisted.python.failurer   r   ZIAddressr&   Z
ITransportZITLSTransportr(   rh   rj   rk   r   rƒ   rˆ   r‰   r–   r   r   r   r   Ú<module>   sD    HS   ù
=ù
5>