U
    2ÜŸj
J  ã                   @  sL  d Z ddlmZ ddlZzddlmZ W n ek
r<   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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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
é    )ÚannotationsN)ÚError)ÚdirectlyProvidesÚimplementer)ÚerrorÚ
interfaces)ÚTCP4ClientEndpointÚTCP4ServerEndpoint)ÚConnectionRefusedError)ÚFactoryÚProtocol)ÚMemoryReactorÚMemoryReactorClock)ÚFailurec                   @  s*   e Zd Zdd„ Zd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-4b529toj/twisted/test/iosim.pyÚ__init__   s    zTLSNegotiation.__init__Ústr©Ú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   r   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d	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#d0d1„ Z$d2d3„ Z%d4d5„ Z&d6d7„ Z'd8d9„ Z(d:d;„ 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   r0   r1   r5   r6   r   r   r   r   H   s    
zFakeTransport.__init__r   r   c                 C  s    d  | jrdpd| j| jjj¡S )NzFakeTransport<{},{},{}>ÚSÚC)Úformatr1   r4   r0   Ú	__class__r%   r   r   r   r   r   d   s
    ýzFakeTransport.__repr__c                 C  s2   | j r
d S | jd k	r"| j |¡ n| j |¡ d S r   )ÚdisconnectingÚtlsÚtlsbufÚappendr2   )r   Údatar   r   r   Úwritek   s
    
zFakeTransport.writec                 C  s   | j r| js| j  ¡  d S r   ©ÚproducerÚstreamingProducerÚresumeProducingr   r   r   r   Ú_checkProduceru   s    zFakeTransport._checkProducerc                 C  s   || _ || _|s| ¡  dS )z.
        From abstract.FileDescriptor
        NrA   )r   rB   Z	streamingr   r   r   ÚregisterProducer{   s    zFakeTransport.registerProducerc                 C  s
   d | _ d S r   )rB   r   r   r   r   ÚunregisterProducer„   s    z FakeTransport.unregisterProducerc                 C  s   |   ¡  |  ¡  d S r   )rG   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©r;   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.
        TNrL   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!   r0   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   )r6   r   r   r   r   ÚgetPeer§   s    zFakeTransport.getPeerc                 C  s   | j S r   )r5   r   r   r   r   ÚgetHostª   s    zFakeTransport.getHostc                 C  s   d S r   r   r   r   r   r   rD   ­   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   )r1   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)r2   rI   r<   r   r   )r   r7   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 rK   )Ú
isinstancer   r<   ÚAssertionErrorr   r$   r=   rJ   r   r   ZISSLTransportr   r0   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Úcountr3   Úclosedr;   Údisconnectedr   ZConnectionDoner!   rB   rC   r<   r   r   r@   rE   rF   rG   rH   rJ   r"   rM   rO   rP   rQ   rR   rD   rS   rT   rU   rV   r[   r\   r]   r^   r`   ra   r   r   r   r   r*   6   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©r1   ©r*   )ÚclientProtocolr   r   r   ÚmakeFakeClientþ   s    
rj   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}
    Trg   rh   )ÚserverProtocolr   r   r   ÚmakeFakeServer  s    
rl   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   rn   ro   rp   rq   rr   rs   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ÚpumprX   )r   rr   Ú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)rs   Zadvancerr   Úprintrq   rV   rp   rE   Úreprr[   r;   rf   rO   )r   rr   rv   ZsDataZcDatar   r   r   ru   9  sF    








zIOPump.pump)N)FT)FT)r%   r&   r'   r)   r   ry   ru   r   r   r   r   rm     s   


rm   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}
    ©rs   )ZmakeConnectionrm   ry   )rk   ÚserverTransportri   ÚclientTransportrr   Úgreetrs   ru   r   r   r   Úconnectf  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serverTransportFactoryrr   r€   rs   Ú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                   @  sN   e Zd ZdZdddœdd„Zdd	d	d
dœdd„Zeeƒ ƒfdddœ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.
    r   ÚNone)ÚmemoryReactorr   c                 C  s
   || _ dS )zƒ
        Create a L{ConnectionCompleter} from a L{MemoryReactor}.

        @param memoryReactor: The reactor to attach to.
        N)Ú_reactor)r   r�   r   r   r   r   û  s    zConnectionCompleter.__init__FTÚboolzIOPump | None)rr   r€   r   c              
   C  sœ   | j }t|jƒD ]†\}}|jD ]v}t||ƒ}|r|j |¡ |j |¡ |\}}	| d¡}
|	 d¡}t	|ƒ}t
|
ƒ}t|||
|||d�}|    S qqdS )aQ  
        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.

        @return: a pump for the connection, or L{None} if no connection could
            be established.
        N)r€   )rŽ   Ú	enumerateÚ
tcpClientsZ
tcpServersrŠ   ÚremoveÚ
connectorsÚpopZbuildProtocolrl   rj   r�   )r   rr   r€   r�   Z	clientIdxr†   r‡   Z	factoriesrˆ   r‰   ri   rk   r~   r   rw   r   r   r   ÚsucceedOnce  s,    



úzConnectionCompleter.succeedOncer   )Úreasonr   c                 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.
        r   é   N)rŽ   r‘   r”   ZclientConnectionFailedr“   )r   r–   r   r   r   ÚfailOnce%  s     ÿzConnectionCompleter.failOnceN)FT)	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‹   )rr   ZreactorZclientEndpointZserverEndpointr   r   r   ÚconnectableEndpoint1  s
    
rš   )FTN)F)*r)   Ú
__future__r   rc   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   r   Ztwisted.python.failurer   r   ZIAddressr(   Z
ITransportZITLSTransportZ	IConsumerr*   rj   rl   rm   r�   r…   rŠ   r‹   rš   r   r   r   r   Ú<module>   sF    HS   ù
=ù
5=